sockets.c 102 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256
  1. /**
  2. * @file
  3. * Sockets BSD-Like API module
  4. *
  5. */
  6. /*
  7. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without modification,
  11. * are permitted provided that the following conditions are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * 3. The name of the author may not be used to endorse or promote products
  19. * derived from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  24. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  26. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  29. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  30. * OF SUCH DAMAGE.
  31. *
  32. * This file is part of the lwIP TCP/IP stack.
  33. *
  34. * Author: Adam Dunkels <adam@sics.se>
  35. *
  36. * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
  37. *
  38. */
  39. #include "lwip/opt.h"
  40. #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
  41. #include "lwip/sockets.h"
  42. #include "lwip/api.h"
  43. #include "lwip/sys.h"
  44. #include "lwip/igmp.h"
  45. #include "lwip/inet.h"
  46. #include "lwip/tcp.h"
  47. #include "lwip/raw.h"
  48. #include "lwip/udp.h"
  49. #include "lwip/memp.h"
  50. #include "lwip/pbuf.h"
  51. #include "lwip/priv/tcpip_priv.h"
  52. #include "lwip/priv/api_msg.h"
  53. //#include "esp_common.h"
  54. #if LWIP_CHECKSUM_ON_COPY
  55. #include "lwip/inet_chksum.h"
  56. #endif
  57. #include <string.h>
  58. /* If the netconn API is not required publicly, then we include the necessary
  59. files here to get the implementation */
  60. #if !LWIP_NETCONN
  61. #undef LWIP_NETCONN
  62. #define LWIP_NETCONN 1
  63. #include "api_msg.c"
  64. #include "api_lib.c"
  65. #include "netbuf.c"
  66. #undef LWIP_NETCONN
  67. #define LWIP_NETCONN 0
  68. #endif
  69. #if LWIP_IPV4
  70. #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
  71. (sin)->sin_len = sizeof(struct sockaddr_in); \
  72. (sin)->sin_family = AF_INET; \
  73. (sin)->sin_port = htons((port)); \
  74. inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \
  75. memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
  76. #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
  77. inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
  78. (port) = ntohs((sin)->sin_port); }while(0)
  79. #endif /* LWIP_IPV4 */
  80. #if LWIP_IPV6
  81. #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
  82. (sin6)->sin6_len = sizeof(struct sockaddr_in6); \
  83. (sin6)->sin6_family = AF_INET6; \
  84. (sin6)->sin6_port = htons((port)); \
  85. (sin6)->sin6_flowinfo = 0; \
  86. inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
  87. (sin6)->sin6_scope_id = 0; }while(0)
  88. #define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
  89. inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
  90. (port) = ntohs((sin6)->sin6_port); }while(0)
  91. #endif /* LWIP_IPV6 */
  92. #if LWIP_IPV4 && LWIP_IPV6
  93. static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port);
  94. #define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \
  95. ((namelen) == sizeof(struct sockaddr_in6)))
  96. #define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \
  97. ((name)->sa_family == AF_INET6))
  98. #define SOCK_ADDR_TYPE_MATCH(name, sock) \
  99. ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
  100. (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
  101. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
  102. if (IP_IS_V6(ipaddr)) { \
  103. IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
  104. } else { \
  105. IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
  106. } } while(0)
  107. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port))
  108. #define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
  109. (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
  110. #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
  111. #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6))
  112. #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6)
  113. #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
  114. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
  115. IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port)
  116. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
  117. SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port)
  118. #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
  119. #else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */
  120. #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in))
  121. #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)
  122. #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
  123. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
  124. IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port)
  125. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
  126. SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
  127. #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
  128. #endif /* LWIP_IPV6 */
  129. #define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \
  130. IS_SOCK_ADDR_TYPE_VALID(name))
  131. #define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
  132. SOCK_ADDR_TYPE_MATCH(name, sock))
  133. #define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0)
  134. #define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0)
  135. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \
  136. LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
  137. if ((sock)->conn == NULL) { return EINVAL; } }while(0)
  138. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \
  139. LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
  140. if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0)
  141. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \
  142. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \
  143. if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0)
  144. #define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name)
  145. #define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name)
  146. #define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name)
  147. #if LWIP_MPU_COMPATIBLE
  148. #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \
  149. name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \
  150. if (name == NULL) { \
  151. sock_set_errno(sock, ENOMEM); \
  152. return -1; \
  153. } }while(0)
  154. #else /* LWIP_MPU_COMPATIBLE */
  155. #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock)
  156. #endif /* LWIP_MPU_COMPATIBLE */
  157. #if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
  158. #define LWIP_SO_SNDRCVTIMEO_OPTTYPE int
  159. #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val))
  160. #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval))
  161. #else
  162. #define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval
  163. #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \
  164. s32_t loc = (val); \
  165. ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \
  166. ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0)
  167. #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U))
  168. #endif
  169. #define NUM_SOCKETS MEMP_NUM_NETCONN
  170. /** This is overridable for the rare case where more than 255 threads
  171. * select on the same socket...
  172. */
  173. #ifndef SELWAIT_T
  174. #define SELWAIT_T u8_t
  175. #endif
  176. /** Contains all internal pointers and states used for a socket */
  177. struct lwip_sock {
  178. /** sockets currently are built on netconns, each socket has one netconn */
  179. struct netconn *conn;
  180. /** data that was left from the previous read */
  181. void *lastdata;
  182. /** offset in the data that was left from the previous read */
  183. u16_t lastoffset;
  184. /** number of times data was received, set by event_callback(),
  185. tested by the receive and select functions */
  186. s16_t rcvevent;
  187. /** number of times data was ACKed (free send buffer), set by event_callback(),
  188. tested by select */
  189. u16_t sendevent;
  190. /** error happened for this socket, set by event_callback(), tested by select */
  191. u16_t errevent;
  192. /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */
  193. u8_t err;
  194. #if ESP_THREAD_SAFE
  195. /* lock is used to protect state/ref field, however this lock is not a perfect lock, e.g
  196. * taskA and taskB can access sock X, then taskA freed sock X, before taskB detect
  197. * this, taskC reuse sock X, then when taskB try to access sock X, problem may happen.
  198. * A mitigation solution may be, when allocate a socket, alloc the least frequently used
  199. * socket.
  200. */
  201. sys_mutex_t lock;
  202. /* can be LWIP_SOCK_OPEN/LWIP_SOCK_CLOSING/LWIP_SOCK_CLOSED */
  203. u8_t state;
  204. /* if ref is 0, the sock need/can to be freed */
  205. s8_t ref;
  206. /* indicate how long the sock is in LWIP_SOCK_CLOSED status */
  207. u8_t age;
  208. #endif
  209. /** counter of how many threads are waiting for this socket using select */
  210. SELWAIT_T select_waiting;
  211. };
  212. #if ESP_THREAD_SAFE
  213. #define LWIP_SOCK_OPEN 0
  214. #define LWIP_SOCK_CLOSING 1
  215. #define LWIP_SOCK_CLOSED 2
  216. #define LWIP_SOCK_LOCK(sock) \
  217. do{\
  218. /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l\n"));*/\
  219. sys_mutex_lock(&sock->lock);\
  220. /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l ok\n"));*/\
  221. }while(0)
  222. #define LWIP_SOCK_UNLOCK(sock) \
  223. do{\
  224. sys_mutex_unlock(&sock->lock);\
  225. /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG1, ("unl\n"));*/\
  226. }while(0)
  227. #define LWIP_FREE_SOCK(sock) \
  228. do{\
  229. if(sock->conn && NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP){\
  230. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free tcp sock\n"));\
  231. free_socket(sock, 1);\
  232. } else {\
  233. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free non-tcp sock\n"));\
  234. free_socket(sock, 0);\
  235. }\
  236. }while(0)
  237. #define LWIP_SET_CLOSE_FLAG() \
  238. do{\
  239. LWIP_SOCK_LOCK(__sock);\
  240. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mark sock closing\n"));\
  241. __sock->state = LWIP_SOCK_CLOSING;\
  242. LWIP_SOCK_UNLOCK(__sock);\
  243. }while(0)
  244. #define LWIP_API_LOCK() \
  245. struct lwip_sock *__sock;\
  246. int __ret;\
  247. \
  248. __sock = get_socket(s);\
  249. if (!__sock) {\
  250. return -1;\
  251. }\
  252. \
  253. do{\
  254. LWIP_SOCK_LOCK(__sock);\
  255. __sock->ref ++;\
  256. if (__sock->state != LWIP_SOCK_OPEN) {\
  257. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_LOCK:soc is %d, return\n", __sock->state));\
  258. __sock->ref --;\
  259. LWIP_SOCK_UNLOCK(__sock);\
  260. return -1;\
  261. }\
  262. \
  263. LWIP_SOCK_UNLOCK(__sock);\
  264. }while(0)
  265. #define LWIP_API_UNLOCK() \
  266. do{\
  267. LWIP_SOCK_LOCK(__sock);\
  268. __sock->ref --;\
  269. if (__sock->state == LWIP_SOCK_CLOSING) {\
  270. if (__sock->ref == 0){\
  271. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK:ref 0, free __sock\n"));\
  272. LWIP_FREE_SOCK(__sock);\
  273. LWIP_SOCK_UNLOCK(__sock);\
  274. return __ret;\
  275. }\
  276. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK: soc state is closing, return\n"));\
  277. LWIP_SOCK_UNLOCK(__sock);\
  278. return __ret;\
  279. }\
  280. \
  281. LWIP_SOCK_UNLOCK(__sock);\
  282. return __ret;\
  283. }while(0)
  284. #endif
  285. #if LWIP_NETCONN_SEM_PER_THREAD
  286. #define SELECT_SEM_T sys_sem_t*
  287. #define SELECT_SEM_PTR(sem) (sem)
  288. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  289. #define SELECT_SEM_T sys_sem_t
  290. #define SELECT_SEM_PTR(sem) (&(sem))
  291. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  292. /** Description for a task waiting in select */
  293. struct lwip_select_cb {
  294. /** Pointer to the next waiting task */
  295. struct lwip_select_cb *next;
  296. /** Pointer to the previous waiting task */
  297. struct lwip_select_cb *prev;
  298. /** readset passed to select */
  299. fd_set *readset;
  300. /** writeset passed to select */
  301. fd_set *writeset;
  302. /** unimplemented: exceptset passed to select */
  303. fd_set *exceptset;
  304. /** don't signal the same semaphore twice: set to 1 when signalled */
  305. int sem_signalled;
  306. /** semaphore to wake up a task waiting for select */
  307. SELECT_SEM_T sem;
  308. };
  309. /** A struct sockaddr replacement that has the same alignment as sockaddr_in/
  310. * sockaddr_in6 if instantiated.
  311. */
  312. union sockaddr_aligned {
  313. struct sockaddr sa;
  314. #if LWIP_IPV6
  315. struct sockaddr_in6 sin6;
  316. #endif /* LWIP_IPV6 */
  317. #if LWIP_IPV4
  318. struct sockaddr_in sin;
  319. #endif /* LWIP_IPV4 */
  320. };
  321. #if LWIP_IGMP
  322. /* Define the number of IPv4 multicast memberships, default is one per socket */
  323. #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
  324. #define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
  325. #endif
  326. /* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
  327. a socket is closed */
  328. struct lwip_socket_multicast_pair {
  329. /** the socket (+1 to not require initialization) */
  330. int sa;
  331. /** the interface address */
  332. ip4_addr_t if_addr;
  333. /** the group address */
  334. ip4_addr_t multi_addr;
  335. };
  336. struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
  337. static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
  338. static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
  339. static void lwip_socket_drop_registered_memberships(int s);
  340. #endif /* LWIP_IGMP */
  341. /** The global array of available sockets */
  342. static struct lwip_sock sockets[NUM_SOCKETS];
  343. #if ESP_THREAD_SAFE
  344. static bool sockets_init_flag = false;
  345. #endif
  346. /** The global list of tasks waiting for select */
  347. static struct lwip_select_cb *select_cb_list;
  348. /** This counter is increased from lwip_select when the list is changed
  349. and checked in event_callback to see if it has changed. */
  350. static volatile int select_cb_ctr;
  351. /** Table to quickly map an lwIP error (err_t) to a socket error
  352. * by using -err as an index */
  353. static const int err_to_errno_table[] = {
  354. 0, /* ERR_OK 0 No error, everything OK. */
  355. ENOMEM, /* ERR_MEM -1 Out of memory error. */
  356. ENOBUFS, /* ERR_BUF -2 Buffer error. */
  357. EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
  358. EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
  359. EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
  360. EINVAL, /* ERR_VAL -6 Illegal value. */
  361. EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
  362. EADDRINUSE, /* ERR_USE -8 Address in use. */
  363. #if ESP_LWIP
  364. EALREADY, /* ERR_ALREADY -9 Already connected. */
  365. EISCONN, /* ERR_ISCONN -10 Conn already established */
  366. ECONNABORTED, /* ERR_ABRT -11 Connection aborted. */
  367. ECONNRESET, /* ERR_RST -12 Connection reset. */
  368. ENOTCONN, /* ERR_CLSD -13 Connection closed. */
  369. ENOTCONN, /* ERR_CONN -14 Not connected. */
  370. EIO, /* ERR_ARG -15 Illegal argument. */
  371. -1, /* ERR_IF -16 Low-level netif error */
  372. #else
  373. EALREADY, /* ERR_ALREADY -9 Already connecting. */
  374. EISCONN, /* ERR_ISCONN -10 Conn already established.*/
  375. ENOTCONN, /* ERR_CONN -11 Not connected. */
  376. -1, /* ERR_IF -12 Low-level netif error */
  377. ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
  378. ECONNRESET, /* ERR_RST -14 Connection reset. */
  379. ENOTCONN, /* ERR_CLSD -15 Connection closed. */
  380. EIO /* ERR_ARG -16 Illegal argument. */
  381. #endif
  382. };
  383. #define ERR_TO_ERRNO_TABLE_SIZE LWIP_ARRAYSIZE(err_to_errno_table)
  384. #define err_to_errno(err) \
  385. ((unsigned)(-(signed)(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
  386. err_to_errno_table[-(signed)(err)] : EIO)
  387. #if LWIP_SOCKET_SET_ERRNO
  388. #ifndef set_errno
  389. #define set_errno(err) do { if (err) { errno = (err); } } while(0)
  390. #endif
  391. #else /* LWIP_SOCKET_SET_ERRNO */
  392. #define set_errno(err)
  393. #endif /* LWIP_SOCKET_SET_ERRNO */
  394. #define sock_set_errno(sk, e) do { \
  395. const int sockerr = (e); \
  396. sk->err = (u8_t)sockerr; \
  397. set_errno(sockerr); \
  398. } while (0)
  399. /* Forward declaration of some functions */
  400. static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
  401. #if !LWIP_TCPIP_CORE_LOCKING
  402. static void lwip_getsockopt_callback(void *arg);
  403. static void lwip_setsockopt_callback(void *arg);
  404. #endif
  405. static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen);
  406. static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen);
  407. #if LWIP_IPV4 && LWIP_IPV6
  408. static void
  409. sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port)
  410. {
  411. if ((sockaddr->sa_family) == AF_INET6) {
  412. SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port);
  413. ipaddr->type = IPADDR_TYPE_V6;
  414. } else {
  415. SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port);
  416. ipaddr->type = IPADDR_TYPE_V4;
  417. }
  418. }
  419. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  420. /** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */
  421. void
  422. lwip_socket_thread_init(void)
  423. {
  424. netconn_thread_init();
  425. }
  426. /** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */
  427. void
  428. lwip_socket_thread_cleanup(void)
  429. {
  430. netconn_thread_cleanup();
  431. }
  432. /**
  433. * Map a externally used socket index to the internal socket representation.
  434. *
  435. * @param s externally used socket index
  436. * @return struct lwip_sock for the socket or NULL if not found
  437. */
  438. static struct lwip_sock *
  439. get_socket(int s)
  440. {
  441. struct lwip_sock *sock;
  442. s -= LWIP_SOCKET_OFFSET;
  443. if ((s < 0) || (s >= NUM_SOCKETS)) {
  444. LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET));
  445. set_errno(EBADF);
  446. return NULL;
  447. }
  448. sock = &sockets[s];
  449. if (!sock->conn) {
  450. LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET));
  451. set_errno(EBADF);
  452. return NULL;
  453. }
  454. return sock;
  455. }
  456. /**
  457. * Same as get_socket but doesn't set errno
  458. *
  459. * @param s externally used socket index
  460. * @return struct lwip_sock for the socket or NULL if not found
  461. */
  462. static struct lwip_sock *
  463. tryget_socket(int s)
  464. {
  465. s -= LWIP_SOCKET_OFFSET;
  466. if ((s < 0) || (s >= NUM_SOCKETS)) {
  467. return NULL;
  468. }
  469. if (!sockets[s].conn) {
  470. return NULL;
  471. }
  472. return &sockets[s];
  473. }
  474. /**
  475. * Allocate a new socket for a given netconn.
  476. *
  477. * @param newconn the netconn for which to allocate a socket
  478. * @param accepted 1 if socket has been created by accept(),
  479. * 0 if socket has been created by socket()
  480. * @return the index of the new socket; -1 on error
  481. */
  482. static int
  483. alloc_socket(struct netconn *newconn, int accepted)
  484. {
  485. int i;
  486. SYS_ARCH_DECL_PROTECT(lev);
  487. #if ESP_THREAD_SAFE
  488. bool found = false;
  489. int oldest = -1;
  490. SYS_ARCH_PROTECT(lev);
  491. if (sockets_init_flag == false){
  492. sockets_init_flag = true;
  493. memset(sockets, 0, sizeof(sockets));
  494. }
  495. for (i = 0; i < NUM_SOCKETS; ++i) {
  496. sockets[i].age ++;
  497. if (found == true){
  498. continue;
  499. }
  500. if (!sockets[i].conn && (sockets[i].state == LWIP_SOCK_OPEN)) {
  501. found = true;
  502. oldest = i;
  503. continue;
  504. }
  505. if (!sockets[i].conn){
  506. if (oldest == -1 || sockets[i].age > sockets[oldest].age){
  507. oldest = i;
  508. }
  509. }
  510. }
  511. if ((oldest != -1) && !sockets[oldest].conn) {
  512. found = true;
  513. sockets[oldest].conn = newconn;
  514. }
  515. SYS_ARCH_UNPROTECT(lev);
  516. if (found == true) {
  517. sockets[oldest].lastdata = NULL;
  518. sockets[oldest].lastoffset = 0;
  519. sockets[oldest].rcvevent = 0;
  520. /* TCP sendbuf is empty, but the socket is not yet writable until connected
  521. * (unless it has been created by accept()). */
  522. sockets[oldest].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
  523. sockets[oldest].errevent = 0;
  524. sockets[oldest].err = 0;
  525. sockets[oldest].select_waiting = 0;
  526. sockets[oldest].state = LWIP_SOCK_OPEN;
  527. sockets[oldest].age = 0;
  528. sockets[oldest].ref = 0;
  529. if (!sockets[oldest].lock){
  530. /* one time init and never free */
  531. if (sys_mutex_new(&sockets[oldest].lock) != ERR_OK){
  532. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new sock lock fail\n"));
  533. return -1;
  534. }
  535. }
  536. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: alloc %d ok\n", oldest));
  537. return oldest + LWIP_SOCKET_OFFSET;
  538. }
  539. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: failed\n"));
  540. #else
  541. /* allocate a new socket identifier */
  542. for (i = 0; i < NUM_SOCKETS; ++i) {
  543. /* Protect socket array */
  544. SYS_ARCH_PROTECT(lev);
  545. if (!sockets[i].conn) {
  546. sockets[i].conn = newconn;
  547. /* The socket is not yet known to anyone, so no need to protect
  548. after having marked it as used. */
  549. SYS_ARCH_UNPROTECT(lev);
  550. sockets[i].lastdata = NULL;
  551. sockets[i].lastoffset = 0;
  552. sockets[i].rcvevent = 0;
  553. /* TCP sendbuf is empty, but the socket is not yet writable until connected
  554. * (unless it has been created by accept()). */
  555. sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
  556. sockets[i].errevent = 0;
  557. sockets[i].err = 0;
  558. sockets[i].select_waiting = 0;
  559. return i + LWIP_SOCKET_OFFSET;
  560. }
  561. SYS_ARCH_UNPROTECT(lev);
  562. }
  563. #endif
  564. return -1;
  565. }
  566. /** Free a socket. The socket's netconn must have been
  567. * delete before!
  568. *
  569. * @param sock the socket to free
  570. * @param is_tcp != 0 for TCP sockets, used to free lastdata
  571. */
  572. static void
  573. free_socket(struct lwip_sock *sock, int is_tcp)
  574. {
  575. void *lastdata;
  576. SYS_ARCH_DECL_PROTECT(lev);
  577. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free socket s=%p is_tcp=%d\n", sock, is_tcp));
  578. lastdata = sock->lastdata;
  579. sock->lastdata = NULL;
  580. sock->lastoffset = 0;
  581. sock->err = 0;
  582. #if ESP_THREAD_SAFE
  583. if (sock->conn){
  584. netconn_free(sock->conn);
  585. }
  586. SYS_ARCH_PROTECT(lev);
  587. sock->age = 0;
  588. sock->conn = NULL;
  589. sock->state = LWIP_SOCK_CLOSED;
  590. SYS_ARCH_UNPROTECT(lev);
  591. #endif
  592. /* Protect socket array */
  593. SYS_ARCH_SET(sock->conn, NULL);
  594. /* don't use 'sock' after this line, as another task might have allocated it */
  595. if (lastdata != NULL) {
  596. if (is_tcp) {
  597. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free lastdata pbuf=%p\n", lastdata));
  598. pbuf_free((struct pbuf *)lastdata);
  599. } else {
  600. LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free lastdata, netbuf=%p\n", lastdata));
  601. netbuf_delete((struct netbuf *)lastdata);
  602. }
  603. }
  604. }
  605. /* Below this, the well-known socket functions are implemented.
  606. * Use google.com or opengroup.org to get a good description :-)
  607. *
  608. * Exceptions are documented!
  609. */
  610. int
  611. lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
  612. {
  613. struct lwip_sock *sock, *nsock;
  614. struct netconn *newconn;
  615. ip_addr_t naddr;
  616. u16_t port = 0;
  617. int newsock;
  618. err_t err;
  619. SYS_ARCH_DECL_PROTECT(lev);
  620. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
  621. sock = get_socket(s);
  622. if (!sock) {
  623. return -1;
  624. }
  625. if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
  626. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
  627. sock_set_errno(sock, EWOULDBLOCK);
  628. return -1;
  629. }
  630. /* wait for a new connection */
  631. err = netconn_accept(sock->conn, &newconn);
  632. if (err != ERR_OK) {
  633. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
  634. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  635. sock_set_errno(sock, EOPNOTSUPP);
  636. return EOPNOTSUPP;
  637. }
  638. sock_set_errno(sock, err_to_errno(err));
  639. return -1;
  640. }
  641. LWIP_ASSERT("newconn != NULL", newconn != NULL);
  642. /* Prevent automatic window updates, we do this on our own! */
  643. netconn_set_noautorecved(newconn, 1);
  644. newsock = alloc_socket(newconn, 1);
  645. if (newsock == -1) {
  646. netconn_delete(newconn);
  647. sock_set_errno(sock, ENFILE);
  648. return -1;
  649. }
  650. LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
  651. LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
  652. nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
  653. /* See event_callback: If data comes in right away after an accept, even
  654. * though the server task might not have created a new socket yet.
  655. * In that case, newconn->socket is counted down (newconn->socket--),
  656. * so nsock->rcvevent is >= 1 here!
  657. */
  658. SYS_ARCH_PROTECT(lev);
  659. nsock->rcvevent += (s16_t)(-1 - newconn->socket);
  660. newconn->socket = newsock;
  661. SYS_ARCH_UNPROTECT(lev);
  662. /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
  663. * not be NULL if addr is valid.
  664. */
  665. if (addr != NULL) {
  666. union sockaddr_aligned tempaddr;
  667. /* get the IP address and port of the remote host */
  668. err = netconn_peer(newconn, &naddr, &port);
  669. if (err != ERR_OK) {
  670. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
  671. netconn_delete(newconn);
  672. free_socket(nsock, 1);
  673. sock_set_errno(sock, err_to_errno(err));
  674. return -1;
  675. }
  676. LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
  677. IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
  678. if (*addrlen > tempaddr.sa.sa_len) {
  679. *addrlen = tempaddr.sa.sa_len;
  680. }
  681. MEMCPY(addr, &tempaddr, *addrlen);
  682. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
  683. ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
  684. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
  685. } else {
  686. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock));
  687. }
  688. sock_set_errno(sock, 0);
  689. return newsock;
  690. }
  691. int
  692. lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
  693. {
  694. struct lwip_sock *sock;
  695. ip_addr_t local_addr;
  696. u16_t local_port;
  697. err_t err;
  698. sock = get_socket(s);
  699. if (!sock) {
  700. return -1;
  701. }
  702. if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
  703. /* sockaddr does not match socket type (IPv4/IPv6) */
  704. sock_set_errno(sock, err_to_errno(ERR_VAL));
  705. return -1;
  706. }
  707. /* check size, family and alignment of 'name' */
  708. LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
  709. IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
  710. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  711. LWIP_UNUSED_ARG(namelen);
  712. SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port);
  713. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
  714. ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
  715. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
  716. err = netconn_bind(sock->conn, &local_addr, local_port);
  717. if (err != ERR_OK) {
  718. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
  719. sock_set_errno(sock, err_to_errno(err));
  720. return -1;
  721. }
  722. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
  723. sock_set_errno(sock, 0);
  724. return 0;
  725. }
  726. int
  727. lwip_close(int s)
  728. {
  729. struct lwip_sock *sock;
  730. int is_tcp = 0;
  731. err_t err;
  732. LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: (%d)\n", s));
  733. sock = get_socket(s);
  734. if (!sock) {
  735. LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: sock is null, return -1\n"));
  736. return -1;
  737. }
  738. if (sock->conn != NULL) {
  739. is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
  740. LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: is_tcp=%d\n", is_tcp));
  741. } else {
  742. LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("conn is null\n"));
  743. LWIP_ASSERT("lwip_close: sock->lastdata == NULL", sock->lastdata == NULL);
  744. }
  745. #if LWIP_IGMP
  746. /* drop all possibly joined IGMP memberships */
  747. lwip_socket_drop_registered_memberships(s);
  748. #endif /* LWIP_IGMP */
  749. err = netconn_delete(sock->conn);
  750. if (err != ERR_OK) {
  751. LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("netconn_delete fail, ret=%d\n", err));
  752. sock_set_errno(sock, err_to_errno(err));
  753. return -1;
  754. }
  755. #if !ESP_THREAD_SAFE
  756. free_socket(sock, is_tcp);
  757. #endif
  758. set_errno(0);
  759. return 0;
  760. }
  761. int
  762. lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
  763. {
  764. struct lwip_sock *sock;
  765. err_t err;
  766. sock = get_socket(s);
  767. if (!sock) {
  768. return -1;
  769. }
  770. if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
  771. /* sockaddr does not match socket type (IPv4/IPv6) */
  772. sock_set_errno(sock, err_to_errno(ERR_VAL));
  773. return -1;
  774. }
  775. LWIP_UNUSED_ARG(namelen);
  776. if (name->sa_family == AF_UNSPEC) {
  777. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
  778. err = netconn_disconnect(sock->conn);
  779. } else {
  780. ip_addr_t remote_addr;
  781. u16_t remote_port;
  782. /* check size, family and alignment of 'name' */
  783. LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
  784. IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
  785. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  786. SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port);
  787. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
  788. ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
  789. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
  790. err = netconn_connect(sock->conn, &remote_addr, remote_port);
  791. }
  792. if (err != ERR_OK) {
  793. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
  794. sock_set_errno(sock, err_to_errno(err));
  795. return -1;
  796. }
  797. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
  798. sock_set_errno(sock, 0);
  799. return 0;
  800. }
  801. /**
  802. * Set a socket into listen mode.
  803. * The socket may not have been used for another connection previously.
  804. *
  805. * @param s the socket to set to listening mode
  806. * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
  807. * @return 0 on success, non-zero on failure
  808. */
  809. int
  810. lwip_listen(int s, int backlog)
  811. {
  812. struct lwip_sock *sock;
  813. err_t err;
  814. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
  815. sock = get_socket(s);
  816. if (!sock) {
  817. return -1;
  818. }
  819. /* limit the "backlog" parameter to fit in an u8_t */
  820. backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
  821. err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
  822. if (err != ERR_OK) {
  823. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
  824. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  825. sock_set_errno(sock, EOPNOTSUPP);
  826. return -1;
  827. }
  828. sock_set_errno(sock, err_to_errno(err));
  829. return -1;
  830. }
  831. sock_set_errno(sock, 0);
  832. return 0;
  833. }
  834. int
  835. lwip_recvfrom(int s, void *mem, size_t len, int flags,
  836. struct sockaddr *from, socklen_t *fromlen)
  837. {
  838. struct lwip_sock *sock;
  839. void *buf = NULL;
  840. struct pbuf *p;
  841. u16_t buflen, copylen;
  842. int off = 0;
  843. u8_t done = 0;
  844. err_t err;
  845. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
  846. sock = get_socket(s);
  847. if (!sock) {
  848. return -1;
  849. }
  850. do {
  851. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
  852. /* Check if there is data left from the last recv operation. */
  853. if (sock->lastdata) {
  854. buf = sock->lastdata;
  855. } else {
  856. /* If this is non-blocking call, then check first */
  857. if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
  858. (sock->rcvevent <= 0)) {
  859. if (off > 0) {
  860. /* update receive window */
  861. netconn_recved(sock->conn, (u32_t)off);
  862. /* already received data, return that */
  863. sock_set_errno(sock, 0);
  864. return off;
  865. }
  866. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
  867. sock_set_errno(sock, EWOULDBLOCK);
  868. return -1;
  869. }
  870. /* No data was left from the previous operation, so we try to get
  871. some from the network. */
  872. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  873. err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
  874. } else {
  875. err = netconn_recv(sock->conn, (struct netbuf **)&buf);
  876. }
  877. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
  878. err, buf));
  879. if (err != ERR_OK) {
  880. if (off > 0) {
  881. /* update receive window */
  882. netconn_recved(sock->conn, (u32_t)off);
  883. if (err == ERR_CLSD) {
  884. /* closed but already received data, ensure select gets the FIN, too */
  885. event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
  886. }
  887. /* already received data, return that */
  888. sock_set_errno(sock, 0);
  889. return off;
  890. }
  891. /* We should really do some error checking here. */
  892. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
  893. s, lwip_strerr(err)));
  894. sock_set_errno(sock, err_to_errno(err));
  895. if (err == ERR_CLSD) {
  896. return 0;
  897. } else {
  898. return -1;
  899. }
  900. }
  901. LWIP_ASSERT("buf != NULL", buf != NULL);
  902. sock->lastdata = buf;
  903. }
  904. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  905. p = (struct pbuf *)buf;
  906. } else {
  907. p = ((struct netbuf *)buf)->p;
  908. }
  909. buflen = p->tot_len;
  910. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
  911. buflen, len, off, sock->lastoffset));
  912. buflen -= sock->lastoffset;
  913. if (len > buflen) {
  914. copylen = buflen;
  915. } else {
  916. copylen = (u16_t)len;
  917. }
  918. /* copy the contents of the received buffer into
  919. the supplied memory pointer mem */
  920. pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
  921. off += copylen;
  922. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  923. LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
  924. len -= copylen;
  925. if ((len <= 0) ||
  926. (p->flags & PBUF_FLAG_PUSH) ||
  927. (sock->rcvevent <= 0) ||
  928. ((flags & MSG_PEEK) != 0)) {
  929. done = 1;
  930. }
  931. } else {
  932. done = 1;
  933. }
  934. /* Check to see from where the data was.*/
  935. if (done) {
  936. #if !SOCKETS_DEBUG
  937. if (from && fromlen)
  938. #endif /* !SOCKETS_DEBUG */
  939. {
  940. u16_t port;
  941. ip_addr_t tmpaddr;
  942. ip_addr_t *fromaddr;
  943. union sockaddr_aligned saddr;
  944. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
  945. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  946. fromaddr = &tmpaddr;
  947. netconn_getaddr(sock->conn, fromaddr, &port, 0);
  948. } else {
  949. port = netbuf_fromport((struct netbuf *)buf);
  950. fromaddr = netbuf_fromaddr((struct netbuf *)buf);
  951. }
  952. IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
  953. ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
  954. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
  955. if (from && fromlen)
  956. {
  957. if (*fromlen > saddr.sa.sa_len) {
  958. *fromlen = saddr.sa.sa_len;
  959. }
  960. MEMCPY(from, &saddr, *fromlen);
  961. #if ESP_LWIP
  962. } else {
  963. /*fix the code for setting the UDP PROTO's remote infomation by liuh at 2014.8.27*/
  964. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){
  965. sock->conn->pcb.udp->remote_ip.u_addr.ip4.addr = fromaddr->u_addr.ip4.addr;
  966. sock->conn->pcb.udp->remote_port = port;
  967. }
  968. #endif
  969. }
  970. }
  971. }
  972. /* If we don't peek the incoming message... */
  973. if ((flags & MSG_PEEK) == 0) {
  974. /* If this is a TCP socket, check if there is data left in the
  975. buffer. If so, it should be saved in the sock structure for next
  976. time around. */
  977. if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
  978. sock->lastdata = buf;
  979. sock->lastoffset += copylen;
  980. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
  981. } else {
  982. sock->lastdata = NULL;
  983. sock->lastoffset = 0;
  984. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
  985. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  986. pbuf_free((struct pbuf *)buf);
  987. } else {
  988. netbuf_delete((struct netbuf *)buf);
  989. }
  990. buf = NULL;
  991. }
  992. }
  993. } while (!done);
  994. if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) &&
  995. ((flags & MSG_PEEK) == 0)) {
  996. /* update receive window */
  997. netconn_recved(sock->conn, (u32_t)off);
  998. }
  999. sock_set_errno(sock, 0);
  1000. return off;
  1001. }
  1002. int
  1003. lwip_read(int s, void *mem, size_t len)
  1004. {
  1005. return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
  1006. }
  1007. int
  1008. lwip_recv(int s, void *mem, size_t len, int flags)
  1009. {
  1010. return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
  1011. }
  1012. int
  1013. lwip_send(int s, const void *data, size_t size, int flags)
  1014. {
  1015. struct lwip_sock *sock;
  1016. err_t err;
  1017. u8_t write_flags;
  1018. size_t written;
  1019. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
  1020. s, data, size, flags));
  1021. sock = get_socket(s);
  1022. if (!sock) {
  1023. return -1;
  1024. }
  1025. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  1026. #if (LWIP_UDP || LWIP_RAW)
  1027. return lwip_sendto(s, data, size, flags, NULL, 0);
  1028. #else /* (LWIP_UDP || LWIP_RAW) */
  1029. sock_set_errno(sock, err_to_errno(ERR_ARG));
  1030. return -1;
  1031. #endif /* (LWIP_UDP || LWIP_RAW) */
  1032. }
  1033. write_flags = NETCONN_COPY |
  1034. ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
  1035. ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
  1036. written = 0;
  1037. err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
  1038. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written));
  1039. sock_set_errno(sock, err_to_errno(err));
  1040. return (err == ERR_OK ? (int)written : -1);
  1041. }
  1042. int
  1043. lwip_sendmsg(int s, const struct msghdr *msg, int flags)
  1044. {
  1045. struct lwip_sock *sock;
  1046. struct netbuf *chain_buf;
  1047. u16_t remote_port;
  1048. int i;
  1049. #if LWIP_TCP
  1050. u8_t write_flags;
  1051. size_t written;
  1052. #endif
  1053. int size = 0;
  1054. err_t err = ERR_OK;
  1055. sock = get_socket(s);
  1056. if (!sock) {
  1057. return -1;
  1058. }
  1059. LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL,
  1060. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  1061. LWIP_UNUSED_ARG(msg->msg_control);
  1062. LWIP_UNUSED_ARG(msg->msg_controllen);
  1063. LWIP_UNUSED_ARG(msg->msg_flags);
  1064. LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0),
  1065. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  1066. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  1067. #if LWIP_TCP
  1068. write_flags = NETCONN_COPY |
  1069. ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
  1070. ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
  1071. for (i = 0; i < msg->msg_iovlen; i++) {
  1072. written = 0;
  1073. err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
  1074. if (err == ERR_OK) {
  1075. size += written;
  1076. /* check that the entire IO vector was accepected, if not return a partial write */
  1077. if (written != msg->msg_iov[i].iov_len)
  1078. break;
  1079. }
  1080. /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */
  1081. else if (err == ERR_WOULDBLOCK && size > 0) {
  1082. err = ERR_OK;
  1083. /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */
  1084. break;
  1085. } else {
  1086. size = -1;
  1087. break;
  1088. }
  1089. }
  1090. sock_set_errno(sock, err_to_errno(err));
  1091. return size;
  1092. #else /* LWIP_TCP */
  1093. sock_set_errno(sock, err_to_errno(ERR_ARG));
  1094. return -1;
  1095. #endif /* LWIP_TCP */
  1096. }
  1097. /* else, UDP and RAW NETCONNs */
  1098. #if LWIP_UDP || LWIP_RAW
  1099. LWIP_UNUSED_ARG(flags);
  1100. LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
  1101. IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
  1102. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  1103. /* initialize chain buffer with destination */
  1104. chain_buf = netbuf_new();
  1105. if (!chain_buf) {
  1106. sock_set_errno(sock, err_to_errno(ERR_MEM));
  1107. return -1;
  1108. }
  1109. if (msg->msg_name) {
  1110. SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
  1111. netbuf_fromport(chain_buf) = remote_port;
  1112. }
  1113. #if LWIP_NETIF_TX_SINGLE_PBUF
  1114. for (i = 0; i < msg->msg_iovlen; i++) {
  1115. size += msg->msg_iov[i].iov_len;
  1116. }
  1117. /* Allocate a new netbuf and copy the data into it. */
  1118. if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
  1119. err = ERR_MEM;
  1120. }
  1121. else {
  1122. /* flatten the IO vectors */
  1123. size_t offset = 0;
  1124. for (i = 0; i < msg->msg_iovlen; i++) {
  1125. MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
  1126. offset += msg->msg_iov[i].iov_len;
  1127. }
  1128. #if LWIP_CHECKSUM_ON_COPY
  1129. {
  1130. /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */
  1131. u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
  1132. netbuf_set_chksum(chain_buf, chksum);
  1133. }
  1134. #endif /* LWIP_CHECKSUM_ON_COPY */
  1135. err = ERR_OK;
  1136. }
  1137. #else /* LWIP_NETIF_TX_SINGLE_PBUF */
  1138. /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain
  1139. manually to avoid having to allocate, chain, and delete a netbuf for each iov */
  1140. for (i = 0; i < msg->msg_iovlen; i++) {
  1141. struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
  1142. if (p == NULL) {
  1143. err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */
  1144. break;
  1145. }
  1146. p->payload = msg->msg_iov[i].iov_base;
  1147. LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
  1148. p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
  1149. /* netbuf empty, add new pbuf */
  1150. if (chain_buf->p == NULL) {
  1151. chain_buf->p = chain_buf->ptr = p;
  1152. /* add pbuf to existing pbuf chain */
  1153. } else {
  1154. pbuf_cat(chain_buf->p, p);
  1155. }
  1156. }
  1157. /* save size of total chain */
  1158. if (err == ERR_OK) {
  1159. size = netbuf_len(chain_buf);
  1160. }
  1161. #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
  1162. if (err == ERR_OK) {
  1163. /* send the data */
  1164. err = netconn_send(sock->conn, chain_buf);
  1165. }
  1166. /* deallocated the buffer */
  1167. netbuf_delete(chain_buf);
  1168. sock_set_errno(sock, err_to_errno(err));
  1169. return (err == ERR_OK ? size : -1);
  1170. #else /* LWIP_UDP || LWIP_RAW */
  1171. sock_set_errno(sock, err_to_errno(ERR_ARG));
  1172. return -1;
  1173. #endif /* LWIP_UDP || LWIP_RAW */
  1174. }
  1175. int
  1176. lwip_sendto(int s, const void *data, size_t size, int flags,
  1177. const struct sockaddr *to, socklen_t tolen)
  1178. {
  1179. struct lwip_sock *sock;
  1180. err_t err;
  1181. u16_t short_size;
  1182. u16_t remote_port;
  1183. struct netbuf buf;
  1184. sock = get_socket(s);
  1185. if (!sock) {
  1186. return -1;
  1187. }
  1188. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  1189. #if LWIP_TCP
  1190. return lwip_send(s, data, size, flags);
  1191. #else /* LWIP_TCP */
  1192. LWIP_UNUSED_ARG(flags);
  1193. sock_set_errno(sock, err_to_errno(ERR_ARG));
  1194. return -1;
  1195. #endif /* LWIP_TCP */
  1196. }
  1197. if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
  1198. /* sockaddr does not match socket type (IPv4/IPv6) */
  1199. sock_set_errno(sock, err_to_errno(ERR_VAL));
  1200. return -1;
  1201. }
  1202. /* @todo: split into multiple sendto's? */
  1203. LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
  1204. short_size = (u16_t)size;
  1205. LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
  1206. (IS_SOCK_ADDR_LEN_VALID(tolen) &&
  1207. IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
  1208. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  1209. LWIP_UNUSED_ARG(tolen);
  1210. /* initialize a buffer */
  1211. buf.p = buf.ptr = NULL;
  1212. #if LWIP_CHECKSUM_ON_COPY
  1213. buf.flags = 0;
  1214. #endif /* LWIP_CHECKSUM_ON_COPY */
  1215. if (to) {
  1216. SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
  1217. } else {
  1218. #if ESP_LWIP
  1219. /*fix the code for getting the UDP proto's remote information by liuh at 2014.8.27*/
  1220. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){
  1221. if(NETCONNTYPE_ISIPV6(netconn_type(sock->conn))) {
  1222. memcpy(&buf.addr.u_addr.ip6.addr, sock->conn->pcb.udp->remote_ip.u_addr.ip6.addr,16);
  1223. remote_port = sock->conn->pcb.udp->remote_port;
  1224. IP_SET_TYPE(&buf.addr, IPADDR_TYPE_V6);
  1225. } else {
  1226. buf.addr.u_addr.ip4.addr = sock->conn->pcb.udp->remote_ip.u_addr.ip4.addr;
  1227. remote_port = sock->conn->pcb.udp->remote_port;
  1228. IP_SET_TYPE(&buf.addr, IPADDR_TYPE_V4);
  1229. }
  1230. } else {
  1231. #endif
  1232. remote_port = 0;
  1233. ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
  1234. #if ESP_LWIP
  1235. }
  1236. #endif
  1237. }
  1238. netbuf_fromport(&buf) = remote_port;
  1239. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
  1240. s, data, short_size, flags));
  1241. ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
  1242. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
  1243. /* make the buffer point to the data that should be sent */
  1244. #if LWIP_NETIF_TX_SINGLE_PBUF
  1245. /* Allocate a new netbuf and copy the data into it. */
  1246. if (netbuf_alloc(&buf, short_size) == NULL) {
  1247. err = ERR_MEM;
  1248. } else {
  1249. #if LWIP_CHECKSUM_ON_COPY
  1250. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
  1251. u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
  1252. netbuf_set_chksum(&buf, chksum);
  1253. } else
  1254. #endif /* LWIP_CHECKSUM_ON_COPY */
  1255. {
  1256. MEMCPY(buf.p->payload, data, short_size);
  1257. }
  1258. err = ERR_OK;
  1259. }
  1260. #else /* LWIP_NETIF_TX_SINGLE_PBUF */
  1261. err = netbuf_ref(&buf, data, short_size);
  1262. #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
  1263. if (err == ERR_OK) {
  1264. DBG_PERF_PATH_SET(DBG_PERF_DIR_TX, DBG_PERF_POINT_SOC_OUT);
  1265. /* send the data */
  1266. err = netconn_send(sock->conn, &buf);
  1267. }
  1268. /* deallocated the buffer */
  1269. netbuf_free(&buf);
  1270. sock_set_errno(sock, err_to_errno(err));
  1271. return (err == ERR_OK ? short_size : -1);
  1272. }
  1273. int
  1274. lwip_socket(int domain, int type, int protocol)
  1275. {
  1276. struct netconn *conn;
  1277. int i;
  1278. #if !LWIP_IPV6
  1279. LWIP_UNUSED_ARG(domain); /* @todo: check this */
  1280. #endif /* LWIP_IPV6 */
  1281. /* create a netconn */
  1282. switch (type) {
  1283. case SOCK_RAW:
  1284. conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
  1285. (u8_t)protocol, event_callback);
  1286. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
  1287. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1288. break;
  1289. case SOCK_DGRAM:
  1290. conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
  1291. ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
  1292. event_callback);
  1293. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
  1294. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1295. break;
  1296. case SOCK_STREAM:
  1297. conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
  1298. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
  1299. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1300. if (conn != NULL) {
  1301. /* Prevent automatic window updates, we do this on our own! */
  1302. netconn_set_noautorecved(conn, 1);
  1303. }
  1304. break;
  1305. default:
  1306. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
  1307. domain, type, protocol));
  1308. set_errno(EINVAL);
  1309. return -1;
  1310. }
  1311. if (!conn) {
  1312. LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
  1313. set_errno(ENOBUFS);
  1314. return -1;
  1315. }
  1316. i = alloc_socket(conn, 0);
  1317. if (i == -1) {
  1318. netconn_delete(conn);
  1319. set_errno(ENFILE);
  1320. return -1;
  1321. }
  1322. conn->socket = i;
  1323. LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
  1324. set_errno(0);
  1325. return i;
  1326. }
  1327. int
  1328. lwip_write(int s, const void *data, size_t size)
  1329. {
  1330. return lwip_send(s, data, size, 0);
  1331. }
  1332. int
  1333. lwip_writev(int s, const struct iovec *iov, int iovcnt)
  1334. {
  1335. struct msghdr msg;
  1336. msg.msg_name = NULL;
  1337. msg.msg_namelen = 0;
  1338. /* Hack: we have to cast via number to cast from 'const' pointer to non-const.
  1339. Blame the opengroup standard for this inconsistency. */
  1340. msg.msg_iov = (struct iovec *)(size_t)iov;
  1341. msg.msg_iovlen = iovcnt;
  1342. msg.msg_control = NULL;
  1343. msg.msg_controllen = 0;
  1344. msg.msg_flags = 0;
  1345. return lwip_sendmsg(s, &msg, 0);
  1346. }
  1347. /**
  1348. * Go through the readset and writeset lists and see which socket of the sockets
  1349. * set in the sets has events. On return, readset, writeset and exceptset have
  1350. * the sockets enabled that had events.
  1351. *
  1352. * @param maxfdp1 the highest socket index in the sets
  1353. * @param readset_in: set of sockets to check for read events
  1354. * @param writeset_in: set of sockets to check for write events
  1355. * @param exceptset_in: set of sockets to check for error events
  1356. * @param readset_out: set of sockets that had read events
  1357. * @param writeset_out: set of sockets that had write events
  1358. * @param exceptset_out: set os sockets that had error events
  1359. * @return number of sockets that had events (read/write/exception) (>= 0)
  1360. */
  1361. static int
  1362. lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
  1363. fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
  1364. {
  1365. int i, nready = 0;
  1366. fd_set lreadset, lwriteset, lexceptset;
  1367. struct lwip_sock *sock;
  1368. SYS_ARCH_DECL_PROTECT(lev);
  1369. FD_ZERO(&lreadset);
  1370. FD_ZERO(&lwriteset);
  1371. FD_ZERO(&lexceptset);
  1372. /* Go through each socket in each list to count number of sockets which
  1373. currently match */
  1374. for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
  1375. /* if this FD is not in the set, continue */
  1376. if (!(readset_in && FD_ISSET(i, readset_in)) &&
  1377. !(writeset_in && FD_ISSET(i, writeset_in)) &&
  1378. !(exceptset_in && FD_ISSET(i, exceptset_in))) {
  1379. continue;
  1380. }
  1381. /* First get the socket's status (protected)... */
  1382. SYS_ARCH_PROTECT(lev);
  1383. sock = tryget_socket(i);
  1384. if (sock != NULL) {
  1385. void* lastdata = sock->lastdata;
  1386. s16_t rcvevent = sock->rcvevent;
  1387. u16_t sendevent = sock->sendevent;
  1388. u16_t errevent = sock->errevent;
  1389. SYS_ARCH_UNPROTECT(lev);
  1390. /* ... then examine it: */
  1391. /* See if netconn of this socket is ready for read */
  1392. if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
  1393. FD_SET(i, &lreadset);
  1394. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
  1395. nready++;
  1396. }
  1397. /* See if netconn of this socket is ready for write */
  1398. if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
  1399. FD_SET(i, &lwriteset);
  1400. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
  1401. nready++;
  1402. }
  1403. /* See if netconn of this socket had an error */
  1404. if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
  1405. FD_SET(i, &lexceptset);
  1406. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
  1407. nready++;
  1408. }
  1409. } else {
  1410. SYS_ARCH_UNPROTECT(lev);
  1411. /* continue on to next FD in list */
  1412. }
  1413. }
  1414. /* copy local sets to the ones provided as arguments */
  1415. *readset_out = lreadset;
  1416. *writeset_out = lwriteset;
  1417. *exceptset_out = lexceptset;
  1418. LWIP_ASSERT("nready >= 0", nready >= 0);
  1419. return nready;
  1420. }
  1421. int
  1422. lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
  1423. struct timeval *timeout)
  1424. {
  1425. u32_t waitres = 0;
  1426. int nready;
  1427. fd_set lreadset, lwriteset, lexceptset;
  1428. u32_t msectimeout;
  1429. struct lwip_select_cb select_cb;
  1430. int i;
  1431. int maxfdp2;
  1432. #if LWIP_NETCONN_SEM_PER_THREAD
  1433. int waited = 0;
  1434. #endif
  1435. SYS_ARCH_DECL_PROTECT(lev);
  1436. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
  1437. maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
  1438. timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
  1439. timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
  1440. /* Go through each socket in each list to count number of sockets which
  1441. currently match */
  1442. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1443. /* If we don't have any current events, then suspend if we are supposed to */
  1444. if (!nready) {
  1445. if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
  1446. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
  1447. /* This is OK as the local fdsets are empty and nready is zero,
  1448. or we would have returned earlier. */
  1449. goto return_copy_fdsets;
  1450. }
  1451. /* None ready: add our semaphore to list:
  1452. We don't actually need any dynamic memory. Our entry on the
  1453. list is only valid while we are in this function, so it's ok
  1454. to use local variables. */
  1455. select_cb.next = NULL;
  1456. select_cb.prev = NULL;
  1457. select_cb.readset = readset;
  1458. select_cb.writeset = writeset;
  1459. select_cb.exceptset = exceptset;
  1460. select_cb.sem_signalled = 0;
  1461. #if LWIP_NETCONN_SEM_PER_THREAD
  1462. select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
  1463. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  1464. if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) {
  1465. /* failed to create semaphore */
  1466. set_errno(ENOMEM);
  1467. return -1;
  1468. }
  1469. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  1470. /* Protect the select_cb_list */
  1471. SYS_ARCH_PROTECT(lev);
  1472. /* Put this select_cb on top of list */
  1473. select_cb.next = select_cb_list;
  1474. if (select_cb_list != NULL) {
  1475. select_cb_list->prev = &select_cb;
  1476. }
  1477. select_cb_list = &select_cb;
  1478. /* Increasing this counter tells event_callback that the list has changed. */
  1479. select_cb_ctr++;
  1480. /* Now we can safely unprotect */
  1481. SYS_ARCH_UNPROTECT(lev);
  1482. /* Increase select_waiting for each socket we are interested in */
  1483. maxfdp2 = maxfdp1;
  1484. for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
  1485. if ((readset && FD_ISSET(i, readset)) ||
  1486. (writeset && FD_ISSET(i, writeset)) ||
  1487. (exceptset && FD_ISSET(i, exceptset))) {
  1488. struct lwip_sock *sock;
  1489. SYS_ARCH_PROTECT(lev);
  1490. sock = tryget_socket(i);
  1491. if (sock != NULL) {
  1492. sock->select_waiting++;
  1493. LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
  1494. } else {
  1495. /* Not a valid socket */
  1496. nready = -1;
  1497. maxfdp2 = i;
  1498. SYS_ARCH_UNPROTECT(lev);
  1499. break;
  1500. }
  1501. SYS_ARCH_UNPROTECT(lev);
  1502. }
  1503. }
  1504. if (nready >= 0) {
  1505. /* Call lwip_selscan again: there could have been events between
  1506. the last scan (without us on the list) and putting us on the list! */
  1507. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1508. if (!nready) {
  1509. /* Still none ready, just wait to be woken */
  1510. if (timeout == 0) {
  1511. /* Wait forever */
  1512. msectimeout = 0;
  1513. } else {
  1514. msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
  1515. if (msectimeout == 0) {
  1516. /* Wait 1ms at least (0 means wait forever) */
  1517. msectimeout = 1;
  1518. }
  1519. }
  1520. waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout);
  1521. #if LWIP_NETCONN_SEM_PER_THREAD
  1522. waited = 1;
  1523. #endif
  1524. }
  1525. }
  1526. /* Decrease select_waiting for each socket we are interested in */
  1527. for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) {
  1528. if ((readset && FD_ISSET(i, readset)) ||
  1529. (writeset && FD_ISSET(i, writeset)) ||
  1530. (exceptset && FD_ISSET(i, exceptset))) {
  1531. struct lwip_sock *sock;
  1532. SYS_ARCH_PROTECT(lev);
  1533. sock = tryget_socket(i);
  1534. if (sock != NULL) {
  1535. /* @todo: what if this is a new socket (reallocated?) in this case,
  1536. select_waiting-- would be wrong (a global 'sockalloc' counter,
  1537. stored per socket could help) */
  1538. LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
  1539. if (sock->select_waiting > 0) {
  1540. sock->select_waiting--;
  1541. }
  1542. } else {
  1543. /* Not a valid socket */
  1544. nready = -1;
  1545. }
  1546. SYS_ARCH_UNPROTECT(lev);
  1547. }
  1548. }
  1549. /* Take us off the list */
  1550. SYS_ARCH_PROTECT(lev);
  1551. if (select_cb.next != NULL) {
  1552. select_cb.next->prev = select_cb.prev;
  1553. }
  1554. if (select_cb_list == &select_cb) {
  1555. LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
  1556. select_cb_list = select_cb.next;
  1557. } else {
  1558. LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
  1559. select_cb.prev->next = select_cb.next;
  1560. }
  1561. /* Increasing this counter tells event_callback that the list has changed. */
  1562. select_cb_ctr++;
  1563. SYS_ARCH_UNPROTECT(lev);
  1564. #if LWIP_NETCONN_SEM_PER_THREAD
  1565. if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
  1566. /* don't leave the thread-local semaphore signalled */
  1567. sys_arch_sem_wait(select_cb.sem, 1);
  1568. }
  1569. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  1570. sys_sem_free(&select_cb.sem);
  1571. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  1572. if (nready < 0) {
  1573. /* This happens when a socket got closed while waiting */
  1574. set_errno(EBADF);
  1575. return -1;
  1576. }
  1577. if (waitres == SYS_ARCH_TIMEOUT) {
  1578. /* Timeout */
  1579. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
  1580. /* This is OK as the local fdsets are empty and nready is zero,
  1581. or we would have returned earlier. */
  1582. goto return_copy_fdsets;
  1583. }
  1584. /* See what's set */
  1585. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1586. }
  1587. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
  1588. return_copy_fdsets:
  1589. set_errno(0);
  1590. if (readset) {
  1591. *readset = lreadset;
  1592. }
  1593. if (writeset) {
  1594. *writeset = lwriteset;
  1595. }
  1596. if (exceptset) {
  1597. *exceptset = lexceptset;
  1598. }
  1599. return nready;
  1600. }
  1601. /**
  1602. * Callback registered in the netconn layer for each socket-netconn.
  1603. * Processes recvevent (data available) and wakes up tasks waiting for select.
  1604. */
  1605. static void
  1606. event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
  1607. {
  1608. int s;
  1609. struct lwip_sock *sock;
  1610. struct lwip_select_cb *scb;
  1611. int last_select_cb_ctr;
  1612. SYS_ARCH_DECL_PROTECT(lev);
  1613. LWIP_UNUSED_ARG(len);
  1614. /* Get socket */
  1615. if (conn) {
  1616. s = conn->socket;
  1617. if (s < 0) {
  1618. /* Data comes in right away after an accept, even though
  1619. * the server task might not have created a new socket yet.
  1620. * Just count down (or up) if that's the case and we
  1621. * will use the data later. Note that only receive events
  1622. * can happen before the new socket is set up. */
  1623. SYS_ARCH_PROTECT(lev);
  1624. if (conn->socket < 0) {
  1625. if (evt == NETCONN_EVT_RCVPLUS) {
  1626. conn->socket--;
  1627. }
  1628. SYS_ARCH_UNPROTECT(lev);
  1629. return;
  1630. }
  1631. s = conn->socket;
  1632. SYS_ARCH_UNPROTECT(lev);
  1633. }
  1634. sock = get_socket(s);
  1635. if (!sock) {
  1636. return;
  1637. }
  1638. } else {
  1639. return;
  1640. }
  1641. SYS_ARCH_PROTECT(lev);
  1642. /* Set event as required */
  1643. switch (evt) {
  1644. case NETCONN_EVT_RCVPLUS:
  1645. sock->rcvevent++;
  1646. break;
  1647. case NETCONN_EVT_RCVMINUS:
  1648. sock->rcvevent--;
  1649. break;
  1650. case NETCONN_EVT_SENDPLUS:
  1651. sock->sendevent = 1;
  1652. break;
  1653. case NETCONN_EVT_SENDMINUS:
  1654. sock->sendevent = 0;
  1655. break;
  1656. case NETCONN_EVT_ERROR:
  1657. sock->errevent = 1;
  1658. break;
  1659. default:
  1660. LWIP_ASSERT("unknown event", 0);
  1661. break;
  1662. }
  1663. if (sock->select_waiting == 0) {
  1664. /* noone is waiting for this socket, no need to check select_cb_list */
  1665. SYS_ARCH_UNPROTECT(lev);
  1666. return;
  1667. }
  1668. /* Now decide if anyone is waiting for this socket */
  1669. /* NOTE: This code goes through the select_cb_list list multiple times
  1670. ONLY IF a select was actually waiting. We go through the list the number
  1671. of waiting select calls + 1. This list is expected to be small. */
  1672. /* At this point, SYS_ARCH is still protected! */
  1673. again:
  1674. for (scb = select_cb_list; scb != NULL; scb = scb->next) {
  1675. /* remember the state of select_cb_list to detect changes */
  1676. last_select_cb_ctr = select_cb_ctr;
  1677. if (scb->sem_signalled == 0) {
  1678. /* semaphore not signalled yet */
  1679. int do_signal = 0;
  1680. /* Test this select call for our socket */
  1681. if (sock->rcvevent > 0) {
  1682. if (scb->readset && FD_ISSET(s, scb->readset)) {
  1683. do_signal = 1;
  1684. }
  1685. }
  1686. if (sock->sendevent != 0) {
  1687. if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
  1688. do_signal = 1;
  1689. }
  1690. }
  1691. if (sock->errevent != 0) {
  1692. if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
  1693. do_signal = 1;
  1694. }
  1695. }
  1696. if (do_signal) {
  1697. scb->sem_signalled = 1;
  1698. /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
  1699. lead to the select thread taking itself off the list, invalidating the semaphore. */
  1700. sys_sem_signal(SELECT_SEM_PTR(scb->sem));
  1701. }
  1702. }
  1703. /* unlock interrupts with each step */
  1704. SYS_ARCH_UNPROTECT(lev);
  1705. /* this makes sure interrupt protection time is short */
  1706. SYS_ARCH_PROTECT(lev);
  1707. if (last_select_cb_ctr != select_cb_ctr) {
  1708. /* someone has changed select_cb_list, restart at the beginning */
  1709. goto again;
  1710. }
  1711. }
  1712. SYS_ARCH_UNPROTECT(lev);
  1713. }
  1714. /**
  1715. * Unimplemented: Close one end of a full-duplex connection.
  1716. * Currently, the full connection is closed.
  1717. */
  1718. int
  1719. lwip_shutdown(int s, int how)
  1720. {
  1721. #if ! ESP_LWIP
  1722. struct lwip_sock *sock;
  1723. err_t err;
  1724. u8_t shut_rx = 0, shut_tx = 0;
  1725. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
  1726. sock = get_socket(s);
  1727. if (!sock) {
  1728. return -1;
  1729. }
  1730. if (sock->conn != NULL) {
  1731. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  1732. sock_set_errno(sock, EOPNOTSUPP);
  1733. return -1;
  1734. }
  1735. } else {
  1736. sock_set_errno(sock, ENOTCONN);
  1737. return -1;
  1738. }
  1739. if (how == SHUT_RD) {
  1740. shut_rx = 1;
  1741. } else if (how == SHUT_WR) {
  1742. shut_tx = 1;
  1743. } else if (how == SHUT_RDWR) {
  1744. shut_rx = 1;
  1745. shut_tx = 1;
  1746. } else {
  1747. sock_set_errno(sock, EINVAL);
  1748. return -1;
  1749. }
  1750. err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
  1751. sock_set_errno(sock, err_to_errno(err));
  1752. return (err == ERR_OK ? 0 : -1);
  1753. #else
  1754. return ERR_OK;
  1755. #endif
  1756. }
  1757. static int
  1758. lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
  1759. {
  1760. struct lwip_sock *sock;
  1761. union sockaddr_aligned saddr;
  1762. ip_addr_t naddr;
  1763. u16_t port;
  1764. err_t err;
  1765. sock = get_socket(s);
  1766. if (!sock) {
  1767. return -1;
  1768. }
  1769. /* get the IP address and port */
  1770. /* @todo: this does not work for IPv6, yet */
  1771. err = netconn_getaddr(sock->conn, &naddr, &port, local);
  1772. if (err != ERR_OK) {
  1773. sock_set_errno(sock, err_to_errno(err));
  1774. return -1;
  1775. }
  1776. IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
  1777. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
  1778. ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
  1779. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port));
  1780. if (*namelen > saddr.sa.sa_len) {
  1781. *namelen = saddr.sa.sa_len;
  1782. }
  1783. MEMCPY(name, &saddr, *namelen);
  1784. sock_set_errno(sock, 0);
  1785. return 0;
  1786. }
  1787. int
  1788. lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
  1789. {
  1790. return lwip_getaddrname(s, name, namelen, 0);
  1791. }
  1792. int
  1793. lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
  1794. {
  1795. return lwip_getaddrname(s, name, namelen, 1);
  1796. }
  1797. int
  1798. lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
  1799. {
  1800. u8_t err;
  1801. struct lwip_sock *sock = get_socket(s);
  1802. #if !LWIP_TCPIP_CORE_LOCKING
  1803. LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
  1804. #endif /* !LWIP_TCPIP_CORE_LOCKING */
  1805. if (!sock) {
  1806. return -1;
  1807. }
  1808. if ((NULL == optval) || (NULL == optlen)) {
  1809. sock_set_errno(sock, EFAULT);
  1810. return -1;
  1811. }
  1812. #if LWIP_TCPIP_CORE_LOCKING
  1813. /* core-locking can just call the -impl function */
  1814. LOCK_TCPIP_CORE();
  1815. err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
  1816. UNLOCK_TCPIP_CORE();
  1817. #else /* LWIP_TCPIP_CORE_LOCKING */
  1818. #if LWIP_MPU_COMPATIBLE
  1819. /* MPU_COMPATIBLE copies the optval data, so check for max size here */
  1820. if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
  1821. sock_set_errno(sock, ENOBUFS);
  1822. return -1;
  1823. }
  1824. #endif /* LWIP_MPU_COMPATIBLE */
  1825. LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
  1826. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
  1827. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
  1828. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
  1829. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
  1830. #if !LWIP_MPU_COMPATIBLE
  1831. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
  1832. #endif /* !LWIP_MPU_COMPATIBLE */
  1833. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
  1834. #if LWIP_NETCONN_SEM_PER_THREAD
  1835. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
  1836. #else
  1837. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
  1838. #endif
  1839. err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
  1840. if (err != ERR_OK) {
  1841. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  1842. sock_set_errno(sock, err_to_errno(err));
  1843. return -1;
  1844. }
  1845. sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
  1846. /* write back optlen and optval */
  1847. *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
  1848. #if LWIP_MPU_COMPATIBLE
  1849. memcpy(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
  1850. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
  1851. #endif /* LWIP_MPU_COMPATIBLE */
  1852. /* maybe lwip_getsockopt_internal has changed err */
  1853. err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
  1854. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  1855. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1856. sock_set_errno(sock, err);
  1857. return err ? -1 : 0;
  1858. }
  1859. #if !LWIP_TCPIP_CORE_LOCKING
  1860. /** lwip_getsockopt_callback: only used without CORE_LOCKING
  1861. * to get into the tcpip_thread
  1862. */
  1863. static void
  1864. lwip_getsockopt_callback(void *arg)
  1865. {
  1866. struct lwip_setgetsockopt_data *data;
  1867. LWIP_ASSERT("arg != NULL", arg != NULL);
  1868. data = (struct lwip_setgetsockopt_data*)arg;
  1869. data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
  1870. #if LWIP_MPU_COMPATIBLE
  1871. data->optval,
  1872. #else /* LWIP_MPU_COMPATIBLE */
  1873. data->optval.p,
  1874. #endif /* LWIP_MPU_COMPATIBLE */
  1875. &data->optlen);
  1876. sys_sem_signal((sys_sem_t*)(data->completed_sem));
  1877. }
  1878. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1879. /** lwip_getsockopt_impl: the actual implementation of getsockopt:
  1880. * same argument as lwip_getsockopt, either called directly or through callback
  1881. */
  1882. static u8_t
  1883. lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen)
  1884. {
  1885. u8_t err = 0;
  1886. struct lwip_sock *sock = tryget_socket(s);
  1887. if (!sock) {
  1888. return EBADF;
  1889. }
  1890. switch (level) {
  1891. /* Level: SOL_SOCKET */
  1892. case SOL_SOCKET:
  1893. switch (optname) {
  1894. #if LWIP_TCP
  1895. case SO_ACCEPTCONN:
  1896. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1897. if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
  1898. return ENOPROTOOPT;
  1899. }
  1900. if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
  1901. *(int*)optval = 1;
  1902. } else {
  1903. *(int*)optval = 0;
  1904. }
  1905. break;
  1906. #endif /* LWIP_TCP */
  1907. /* The option flags */
  1908. case SO_BROADCAST:
  1909. case SO_KEEPALIVE:
  1910. #if SO_REUSE
  1911. case SO_REUSEADDR:
  1912. #endif /* SO_REUSE */
  1913. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1914. *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname);
  1915. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
  1916. s, optname, (*(int*)optval?"on":"off")));
  1917. break;
  1918. case SO_TYPE:
  1919. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  1920. switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
  1921. case NETCONN_RAW:
  1922. *(int*)optval = SOCK_RAW;
  1923. break;
  1924. case NETCONN_TCP:
  1925. *(int*)optval = SOCK_STREAM;
  1926. break;
  1927. case NETCONN_UDP:
  1928. *(int*)optval = SOCK_DGRAM;
  1929. break;
  1930. default: /* unrecognized socket type */
  1931. *(int*)optval = netconn_type(sock->conn);
  1932. LWIP_DEBUGF(SOCKETS_DEBUG,
  1933. ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
  1934. s, *(int *)optval));
  1935. } /* switch (netconn_type(sock->conn)) */
  1936. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
  1937. s, *(int *)optval));
  1938. break;
  1939. case SO_ERROR:
  1940. LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int);
  1941. /* only overwrite ERR_OK or temporary errors */
  1942. if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) {
  1943. sock_set_errno(sock, err_to_errno(sock->conn->last_err));
  1944. }
  1945. *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err);
  1946. sock->err = 0;
  1947. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
  1948. s, *(int *)optval));
  1949. break;
  1950. #if LWIP_SO_SNDTIMEO
  1951. case SO_SNDTIMEO:
  1952. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  1953. LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
  1954. break;
  1955. #endif /* LWIP_SO_SNDTIMEO */
  1956. #if LWIP_SO_RCVTIMEO
  1957. case SO_RCVTIMEO:
  1958. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  1959. LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
  1960. break;
  1961. #endif /* LWIP_SO_RCVTIMEO */
  1962. #if LWIP_SO_RCVBUF
  1963. case SO_RCVBUF:
  1964. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  1965. *(int *)optval = netconn_get_recvbufsize(sock->conn);
  1966. break;
  1967. #endif /* LWIP_SO_RCVBUF */
  1968. #if LWIP_SO_LINGER
  1969. case SO_LINGER:
  1970. {
  1971. s16_t conn_linger;
  1972. struct linger* linger = (struct linger*)optval;
  1973. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger);
  1974. conn_linger = sock->conn->linger;
  1975. if (conn_linger >= 0) {
  1976. linger->l_onoff = 1;
  1977. linger->l_linger = (int)conn_linger;
  1978. } else {
  1979. linger->l_onoff = 0;
  1980. linger->l_linger = 0;
  1981. }
  1982. }
  1983. break;
  1984. #endif /* LWIP_SO_LINGER */
  1985. #if LWIP_UDP
  1986. case SO_NO_CHECK:
  1987. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP);
  1988. #if LWIP_UDPLITE
  1989. if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
  1990. /* this flag is only available for UDP, not for UDP lite */
  1991. return EAFNOSUPPORT;
  1992. }
  1993. #endif /* LWIP_UDPLITE */
  1994. *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
  1995. break;
  1996. #endif /* LWIP_UDP*/
  1997. default:
  1998. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
  1999. s, optname));
  2000. err = ENOPROTOOPT;
  2001. break;
  2002. } /* switch (optname) */
  2003. break;
  2004. /* Level: IPPROTO_IP */
  2005. case IPPROTO_IP:
  2006. switch (optname) {
  2007. case IP_TTL:
  2008. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  2009. *(int*)optval = sock->conn->pcb.ip->ttl;
  2010. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
  2011. s, *(int *)optval));
  2012. break;
  2013. case IP_TOS:
  2014. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  2015. *(int*)optval = sock->conn->pcb.ip->tos;
  2016. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
  2017. s, *(int *)optval));
  2018. break;
  2019. #if LWIP_MULTICAST_TX_OPTIONS
  2020. case IP_MULTICAST_TTL:
  2021. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
  2022. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
  2023. return ENOPROTOOPT;
  2024. }
  2025. *(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl;
  2026. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
  2027. s, *(int *)optval));
  2028. break;
  2029. case IP_MULTICAST_IF:
  2030. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr);
  2031. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
  2032. return ENOPROTOOPT;
  2033. }
  2034. inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
  2035. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
  2036. s, *(u32_t *)optval));
  2037. break;
  2038. case IP_MULTICAST_LOOP:
  2039. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
  2040. if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
  2041. *(u8_t*)optval = 1;
  2042. } else {
  2043. *(u8_t*)optval = 0;
  2044. }
  2045. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
  2046. s, *(int *)optval));
  2047. break;
  2048. #endif /* LWIP_MULTICAST_TX_OPTIONS */
  2049. default:
  2050. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
  2051. s, optname));
  2052. err = ENOPROTOOPT;
  2053. break;
  2054. } /* switch (optname) */
  2055. break;
  2056. #if LWIP_TCP
  2057. /* Level: IPPROTO_TCP */
  2058. case IPPROTO_TCP:
  2059. /* Special case: all IPPROTO_TCP option take an int */
  2060. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
  2061. switch (optname) {
  2062. case TCP_NODELAY:
  2063. *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
  2064. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
  2065. s, (*(int*)optval)?"on":"off") );
  2066. break;
  2067. case TCP_KEEPALIVE:
  2068. *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
  2069. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n",
  2070. s, *(int *)optval));
  2071. break;
  2072. #if LWIP_TCP_KEEPALIVE
  2073. case TCP_KEEPIDLE:
  2074. *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
  2075. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n",
  2076. s, *(int *)optval));
  2077. break;
  2078. case TCP_KEEPINTVL:
  2079. *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
  2080. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n",
  2081. s, *(int *)optval));
  2082. break;
  2083. case TCP_KEEPCNT:
  2084. *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
  2085. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n",
  2086. s, *(int *)optval));
  2087. break;
  2088. #endif /* LWIP_TCP_KEEPALIVE */
  2089. #if ESP_PER_SOC_TCP_WND
  2090. case TCP_WINDOW:
  2091. *(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_wnd;
  2092. break;
  2093. case TCP_SNDBUF:
  2094. *(int*)optval = (int)sock->conn->pcb.tcp->per_soc_tcp_snd_buf;
  2095. break;
  2096. #endif
  2097. default:
  2098. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
  2099. s, optname));
  2100. err = ENOPROTOOPT;
  2101. break;
  2102. } /* switch (optname) */
  2103. break;
  2104. #endif /* LWIP_TCP */
  2105. #if LWIP_IPV6
  2106. /* Level: IPPROTO_IPV6 */
  2107. case IPPROTO_IPV6:
  2108. switch (optname) {
  2109. case IPV6_V6ONLY:
  2110. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  2111. /* @todo: this does not work for datagram sockets, yet */
  2112. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  2113. return ENOPROTOOPT;
  2114. }
  2115. *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
  2116. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
  2117. s, *(int *)optval));
  2118. break;
  2119. default:
  2120. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
  2121. s, optname));
  2122. err = ENOPROTOOPT;
  2123. break;
  2124. } /* switch (optname) */
  2125. break;
  2126. #endif /* LWIP_IPV6 */
  2127. #if LWIP_UDP && LWIP_UDPLITE
  2128. /* Level: IPPROTO_UDPLITE */
  2129. case IPPROTO_UDPLITE:
  2130. /* Special case: all IPPROTO_UDPLITE option take an int */
  2131. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  2132. /* If this is no UDP lite socket, ignore any options. */
  2133. if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
  2134. return ENOPROTOOPT;
  2135. }
  2136. switch (optname) {
  2137. case UDPLITE_SEND_CSCOV:
  2138. *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
  2139. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
  2140. s, (*(int*)optval)) );
  2141. break;
  2142. case UDPLITE_RECV_CSCOV:
  2143. *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
  2144. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
  2145. s, (*(int*)optval)) );
  2146. break;
  2147. default:
  2148. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
  2149. s, optname));
  2150. err = ENOPROTOOPT;
  2151. break;
  2152. } /* switch (optname) */
  2153. break;
  2154. #endif /* LWIP_UDP */
  2155. /* Level: IPPROTO_RAW */
  2156. case IPPROTO_RAW:
  2157. switch (optname) {
  2158. #if LWIP_IPV6 && LWIP_RAW
  2159. case IPV6_CHECKSUM:
  2160. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW);
  2161. if (sock->conn->pcb.raw->chksum_reqd == 0) {
  2162. *(int *)optval = -1;
  2163. } else {
  2164. *(int *)optval = sock->conn->pcb.raw->chksum_offset;
  2165. }
  2166. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n",
  2167. s, (*(int*)optval)) );
  2168. break;
  2169. #endif /* LWIP_IPV6 && LWIP_RAW */
  2170. default:
  2171. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
  2172. s, optname));
  2173. err = ENOPROTOOPT;
  2174. break;
  2175. } /* switch (optname) */
  2176. break;
  2177. default:
  2178. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
  2179. s, level, optname));
  2180. err = ENOPROTOOPT;
  2181. break;
  2182. } /* switch (level) */
  2183. return err;
  2184. }
  2185. int
  2186. lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
  2187. {
  2188. u8_t err = 0;
  2189. struct lwip_sock *sock = get_socket(s);
  2190. #if !LWIP_TCPIP_CORE_LOCKING
  2191. LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
  2192. #endif /* !LWIP_TCPIP_CORE_LOCKING */
  2193. if (!sock) {
  2194. return -1;
  2195. }
  2196. if (NULL == optval) {
  2197. sock_set_errno(sock, EFAULT);
  2198. return -1;
  2199. }
  2200. #if LWIP_TCPIP_CORE_LOCKING
  2201. /* core-locking can just call the -impl function */
  2202. LOCK_TCPIP_CORE();
  2203. err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
  2204. UNLOCK_TCPIP_CORE();
  2205. #else /* LWIP_TCPIP_CORE_LOCKING */
  2206. #if LWIP_MPU_COMPATIBLE
  2207. /* MPU_COMPATIBLE copies the optval data, so check for max size here */
  2208. if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
  2209. sock_set_errno(sock, ENOBUFS);
  2210. return -1;
  2211. }
  2212. #endif /* LWIP_MPU_COMPATIBLE */
  2213. LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
  2214. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
  2215. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
  2216. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
  2217. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
  2218. #if LWIP_MPU_COMPATIBLE
  2219. memcpy(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
  2220. #else /* LWIP_MPU_COMPATIBLE */
  2221. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval;
  2222. #endif /* LWIP_MPU_COMPATIBLE */
  2223. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
  2224. #if LWIP_NETCONN_SEM_PER_THREAD
  2225. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
  2226. #else
  2227. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
  2228. #endif
  2229. err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
  2230. if (err != ERR_OK) {
  2231. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  2232. sock_set_errno(sock, err_to_errno(err));
  2233. return -1;
  2234. }
  2235. sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
  2236. /* maybe lwip_getsockopt_internal has changed err */
  2237. err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
  2238. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  2239. #endif /* LWIP_TCPIP_CORE_LOCKING */
  2240. sock_set_errno(sock, err);
  2241. return err ? -1 : 0;
  2242. }
  2243. #if !LWIP_TCPIP_CORE_LOCKING
  2244. /** lwip_setsockopt_callback: only used without CORE_LOCKING
  2245. * to get into the tcpip_thread
  2246. */
  2247. static void
  2248. lwip_setsockopt_callback(void *arg)
  2249. {
  2250. struct lwip_setgetsockopt_data *data;
  2251. LWIP_ASSERT("arg != NULL", arg != NULL);
  2252. data = (struct lwip_setgetsockopt_data*)arg;
  2253. data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
  2254. #if LWIP_MPU_COMPATIBLE
  2255. data->optval,
  2256. #else /* LWIP_MPU_COMPATIBLE */
  2257. data->optval.pc,
  2258. #endif /* LWIP_MPU_COMPATIBLE */
  2259. data->optlen);
  2260. sys_sem_signal((sys_sem_t*)(data->completed_sem));
  2261. }
  2262. #endif /* LWIP_TCPIP_CORE_LOCKING */
  2263. /** lwip_setsockopt_impl: the actual implementation of setsockopt:
  2264. * same argument as lwip_setsockopt, either called directly or through callback
  2265. */
  2266. static u8_t
  2267. lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen)
  2268. {
  2269. u8_t err = 0;
  2270. struct lwip_sock *sock = tryget_socket(s);
  2271. if (!sock) {
  2272. return EBADF;
  2273. }
  2274. switch (level) {
  2275. /* Level: SOL_SOCKET */
  2276. case SOL_SOCKET:
  2277. switch (optname) {
  2278. /* SO_ACCEPTCONN is get-only */
  2279. /* The option flags */
  2280. case SO_BROADCAST:
  2281. case SO_KEEPALIVE:
  2282. #if SO_REUSE
  2283. case SO_REUSEADDR:
  2284. #endif /* SO_REUSE */
  2285. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2286. if (*(const int*)optval) {
  2287. ip_set_option(sock->conn->pcb.ip, optname);
  2288. } else {
  2289. ip_reset_option(sock->conn->pcb.ip, optname);
  2290. }
  2291. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
  2292. s, optname, (*(const int*)optval?"on":"off")));
  2293. break;
  2294. /* SO_TYPE is get-only */
  2295. /* SO_ERROR is get-only */
  2296. #if LWIP_SO_SNDTIMEO
  2297. case SO_SNDTIMEO:
  2298. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  2299. netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
  2300. break;
  2301. #endif /* LWIP_SO_SNDTIMEO */
  2302. #if LWIP_SO_RCVTIMEO
  2303. case SO_RCVTIMEO:
  2304. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  2305. netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
  2306. break;
  2307. #endif /* LWIP_SO_RCVTIMEO */
  2308. #if LWIP_SO_RCVBUF
  2309. case SO_RCVBUF:
  2310. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int);
  2311. netconn_set_recvbufsize(sock->conn, *(const int*)optval);
  2312. break;
  2313. #endif /* LWIP_SO_RCVBUF */
  2314. #if LWIP_SO_LINGER
  2315. case SO_LINGER:
  2316. {
  2317. const struct linger* linger = (const struct linger*)optval;
  2318. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger);
  2319. if (linger->l_onoff) {
  2320. int lingersec = linger->l_linger;
  2321. if (lingersec < 0) {
  2322. return EINVAL;
  2323. }
  2324. if (lingersec > 0xFFFF) {
  2325. lingersec = 0xFFFF;
  2326. }
  2327. sock->conn->linger = (s16_t)lingersec;
  2328. } else {
  2329. sock->conn->linger = -1;
  2330. }
  2331. }
  2332. break;
  2333. #endif /* LWIP_SO_LINGER */
  2334. #if LWIP_UDP
  2335. case SO_NO_CHECK:
  2336. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
  2337. #if LWIP_UDPLITE
  2338. if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
  2339. /* this flag is only available for UDP, not for UDP lite */
  2340. return EAFNOSUPPORT;
  2341. }
  2342. #endif /* LWIP_UDPLITE */
  2343. if (*(const int*)optval) {
  2344. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
  2345. } else {
  2346. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
  2347. }
  2348. break;
  2349. #endif /* LWIP_UDP */
  2350. default:
  2351. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
  2352. s, optname));
  2353. err = ENOPROTOOPT;
  2354. break;
  2355. } /* switch (optname) */
  2356. break;
  2357. /* Level: IPPROTO_IP */
  2358. case IPPROTO_IP:
  2359. switch (optname) {
  2360. case IP_TTL:
  2361. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2362. sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval);
  2363. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
  2364. s, sock->conn->pcb.ip->ttl));
  2365. break;
  2366. case IP_TOS:
  2367. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2368. sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval);
  2369. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
  2370. s, sock->conn->pcb.ip->tos));
  2371. break;
  2372. #if LWIP_MULTICAST_TX_OPTIONS
  2373. case IP_MULTICAST_TTL:
  2374. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
  2375. sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval);
  2376. break;
  2377. case IP_MULTICAST_IF:
  2378. {
  2379. ip4_addr_t if_addr;
  2380. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
  2381. inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval);
  2382. udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
  2383. }
  2384. break;
  2385. case IP_MULTICAST_LOOP:
  2386. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
  2387. if (*(const u8_t*)optval) {
  2388. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
  2389. } else {
  2390. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
  2391. }
  2392. break;
  2393. #endif /* LWIP_MULTICAST_TX_OPTIONS */
  2394. #if LWIP_IGMP
  2395. case IP_ADD_MEMBERSHIP:
  2396. case IP_DROP_MEMBERSHIP:
  2397. {
  2398. /* If this is a TCP or a RAW socket, ignore these options. */
  2399. /* @todo: assign membership to this socket so that it is dropped when state the socket */
  2400. err_t igmp_err;
  2401. const struct ip_mreq *imr = (const struct ip_mreq *)optval;
  2402. ip4_addr_t if_addr;
  2403. ip4_addr_t multi_addr;
  2404. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
  2405. inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
  2406. inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
  2407. if (optname == IP_ADD_MEMBERSHIP) {
  2408. if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
  2409. /* cannot track membership (out of memory) */
  2410. err = ENOMEM;
  2411. igmp_err = ERR_OK;
  2412. } else {
  2413. igmp_err = igmp_joingroup(&if_addr, &multi_addr);
  2414. }
  2415. } else {
  2416. igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
  2417. lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
  2418. }
  2419. if (igmp_err != ERR_OK) {
  2420. err = EADDRNOTAVAIL;
  2421. }
  2422. }
  2423. break;
  2424. #endif /* LWIP_IGMP */
  2425. default:
  2426. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
  2427. s, optname));
  2428. err = ENOPROTOOPT;
  2429. break;
  2430. } /* switch (optname) */
  2431. break;
  2432. #if LWIP_TCP
  2433. /* Level: IPPROTO_TCP */
  2434. case IPPROTO_TCP:
  2435. /* Special case: all IPPROTO_TCP option take an int */
  2436. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
  2437. switch (optname) {
  2438. case TCP_NODELAY:
  2439. if (*(const int*)optval) {
  2440. tcp_nagle_disable(sock->conn->pcb.tcp);
  2441. } else {
  2442. tcp_nagle_enable(sock->conn->pcb.tcp);
  2443. }
  2444. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
  2445. s, (*(const int *)optval)?"on":"off") );
  2446. break;
  2447. case TCP_KEEPALIVE:
  2448. sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval);
  2449. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
  2450. s, sock->conn->pcb.tcp->keep_idle));
  2451. break;
  2452. #if LWIP_TCP_KEEPALIVE
  2453. case TCP_KEEPIDLE:
  2454. sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval);
  2455. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
  2456. s, sock->conn->pcb.tcp->keep_idle));
  2457. break;
  2458. case TCP_KEEPINTVL:
  2459. sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval);
  2460. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
  2461. s, sock->conn->pcb.tcp->keep_intvl));
  2462. break;
  2463. case TCP_KEEPCNT:
  2464. sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval);
  2465. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
  2466. s, sock->conn->pcb.tcp->keep_cnt));
  2467. break;
  2468. #endif /* LWIP_TCP_KEEPALIVE */
  2469. #if ESP_PER_SOC_TCP_WND
  2470. case TCP_WINDOW:
  2471. sock->conn->pcb.tcp->per_soc_tcp_wnd = ((u32_t)(*(const int*)optval)) * TCP_MSS;
  2472. break;
  2473. case TCP_SNDBUF:
  2474. sock->conn->pcb.tcp->per_soc_tcp_snd_buf = ((u32_t)(*(const int*)optval)) * TCP_MSS;
  2475. break;
  2476. #endif
  2477. default:
  2478. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
  2479. s, optname));
  2480. err = ENOPROTOOPT;
  2481. break;
  2482. } /* switch (optname) */
  2483. break;
  2484. #endif /* LWIP_TCP*/
  2485. #if LWIP_IPV6
  2486. /* Level: IPPROTO_IPV6 */
  2487. case IPPROTO_IPV6:
  2488. switch (optname) {
  2489. case IPV6_V6ONLY:
  2490. /* @todo: this does not work for datagram sockets, yet */
  2491. #if CONFIG_MDNS
  2492. //LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
  2493. #else
  2494. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
  2495. #endif
  2496. if (*(const int*)optval) {
  2497. netconn_set_ipv6only(sock->conn, 1);
  2498. } else {
  2499. netconn_set_ipv6only(sock->conn, 0);
  2500. }
  2501. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
  2502. s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
  2503. break;
  2504. default:
  2505. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
  2506. s, optname));
  2507. err = ENOPROTOOPT;
  2508. break;
  2509. } /* switch (optname) */
  2510. break;
  2511. #endif /* LWIP_IPV6 */
  2512. #if LWIP_UDP && LWIP_UDPLITE
  2513. /* Level: IPPROTO_UDPLITE */
  2514. case IPPROTO_UDPLITE:
  2515. /* Special case: all IPPROTO_UDPLITE option take an int */
  2516. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2517. /* If this is no UDP lite socket, ignore any options. */
  2518. if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
  2519. return ENOPROTOOPT;
  2520. }
  2521. switch (optname) {
  2522. case UDPLITE_SEND_CSCOV:
  2523. if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
  2524. /* don't allow illegal values! */
  2525. sock->conn->pcb.udp->chksum_len_tx = 8;
  2526. } else {
  2527. sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval;
  2528. }
  2529. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
  2530. s, (*(const int*)optval)) );
  2531. break;
  2532. case UDPLITE_RECV_CSCOV:
  2533. if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
  2534. /* don't allow illegal values! */
  2535. sock->conn->pcb.udp->chksum_len_rx = 8;
  2536. } else {
  2537. sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval;
  2538. }
  2539. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
  2540. s, (*(const int*)optval)) );
  2541. break;
  2542. default:
  2543. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
  2544. s, optname));
  2545. err = ENOPROTOOPT;
  2546. break;
  2547. } /* switch (optname) */
  2548. break;
  2549. #endif /* LWIP_UDP */
  2550. /* Level: IPPROTO_RAW */
  2551. case IPPROTO_RAW:
  2552. switch (optname) {
  2553. #if LWIP_IPV6 && LWIP_RAW
  2554. case IPV6_CHECKSUM:
  2555. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW);
  2556. if (*(const int *)optval < 0) {
  2557. sock->conn->pcb.raw->chksum_reqd = 0;
  2558. } else if (*(const int *)optval & 1) {
  2559. /* Per RFC3542, odd offsets are not allowed */
  2560. return EINVAL;
  2561. } else {
  2562. sock->conn->pcb.raw->chksum_reqd = 1;
  2563. sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval;
  2564. }
  2565. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n",
  2566. s, sock->conn->pcb.raw->chksum_reqd));
  2567. break;
  2568. #endif /* LWIP_IPV6 && LWIP_RAW */
  2569. default:
  2570. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
  2571. s, optname));
  2572. err = ENOPROTOOPT;
  2573. break;
  2574. } /* switch (optname) */
  2575. break;
  2576. default:
  2577. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
  2578. s, level, optname));
  2579. err = ENOPROTOOPT;
  2580. break;
  2581. } /* switch (level) */
  2582. return err;
  2583. }
  2584. int
  2585. lwip_ioctl(int s, long cmd, void *argp)
  2586. {
  2587. struct lwip_sock *sock = get_socket(s);
  2588. u8_t val;
  2589. #if LWIP_SO_RCVBUF
  2590. u16_t buflen = 0;
  2591. int recv_avail;
  2592. #endif /* LWIP_SO_RCVBUF */
  2593. if (!sock) {
  2594. return -1;
  2595. }
  2596. switch (cmd) {
  2597. #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
  2598. case FIONREAD:
  2599. if (!argp) {
  2600. sock_set_errno(sock, EINVAL);
  2601. return -1;
  2602. }
  2603. #if LWIP_FIONREAD_LINUXMODE
  2604. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  2605. struct pbuf *p;
  2606. if (sock->lastdata) {
  2607. p = ((struct netbuf *)sock->lastdata)->p;
  2608. *((int*)argp) = p->tot_len - sock->lastoffset;
  2609. } else {
  2610. struct netbuf *rxbuf;
  2611. err_t err;
  2612. if (sock->rcvevent <= 0) {
  2613. *((int*)argp) = 0;
  2614. } else {
  2615. err = netconn_recv(sock->conn, &rxbuf);
  2616. if (err != ERR_OK) {
  2617. *((int*)argp) = 0;
  2618. } else {
  2619. sock->lastdata = rxbuf;
  2620. sock->lastoffset = 0;
  2621. *((int*)argp) = rxbuf->p->tot_len;
  2622. }
  2623. }
  2624. }
  2625. return 0;
  2626. }
  2627. #endif /* LWIP_FIONREAD_LINUXMODE */
  2628. #if LWIP_SO_RCVBUF
  2629. /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */
  2630. SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
  2631. if (recv_avail < 0) {
  2632. recv_avail = 0;
  2633. }
  2634. *((int*)argp) = recv_avail;
  2635. /* Check if there is data left from the last recv operation. /maq 041215 */
  2636. if (sock->lastdata) {
  2637. struct pbuf *p = (struct pbuf *)sock->lastdata;
  2638. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  2639. p = ((struct netbuf *)p)->p;
  2640. }
  2641. buflen = p->tot_len;
  2642. buflen -= sock->lastoffset;
  2643. *((int*)argp) += buflen;
  2644. }
  2645. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
  2646. sock_set_errno(sock, 0);
  2647. return 0;
  2648. #else /* LWIP_SO_RCVBUF */
  2649. break;
  2650. #endif /* LWIP_SO_RCVBUF */
  2651. #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */
  2652. case (long)FIONBIO:
  2653. val = 0;
  2654. if (argp && *(u32_t*)argp) {
  2655. val = 1;
  2656. }
  2657. netconn_set_nonblocking(sock->conn, val);
  2658. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
  2659. sock_set_errno(sock, 0);
  2660. return 0;
  2661. default:
  2662. break;
  2663. } /* switch (cmd) */
  2664. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
  2665. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2666. return -1;
  2667. }
  2668. /** A minimal implementation of fcntl.
  2669. * Currently only the commands F_GETFL and F_SETFL are implemented.
  2670. * Only the flag O_NONBLOCK is implemented.
  2671. */
  2672. int
  2673. lwip_fcntl(int s, int cmd, int val)
  2674. {
  2675. struct lwip_sock *sock = get_socket(s);
  2676. int ret = -1;
  2677. if (!sock) {
  2678. return -1;
  2679. }
  2680. switch (cmd) {
  2681. case F_GETFL:
  2682. ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
  2683. sock_set_errno(sock, 0);
  2684. break;
  2685. case F_SETFL:
  2686. if ((val & ~O_NONBLOCK) == 0) {
  2687. /* only O_NONBLOCK, all other bits are zero */
  2688. netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
  2689. ret = 0;
  2690. sock_set_errno(sock, 0);
  2691. } else {
  2692. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2693. }
  2694. break;
  2695. default:
  2696. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
  2697. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2698. break;
  2699. }
  2700. return ret;
  2701. }
  2702. #if LWIP_IGMP
  2703. /** Register a new IGMP membership. On socket close, the membership is dropped automatically.
  2704. *
  2705. * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
  2706. *
  2707. * @return 1 on success, 0 on failure
  2708. */
  2709. static int
  2710. lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
  2711. {
  2712. /* s+1 is stored in the array to prevent having to initialize the array
  2713. (default initialization is to 0) */
  2714. int sa = s + 1;
  2715. int i;
  2716. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2717. if (socket_ipv4_multicast_memberships[i].sa == 0) {
  2718. socket_ipv4_multicast_memberships[i].sa = sa;
  2719. ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
  2720. ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
  2721. return 1;
  2722. }
  2723. }
  2724. return 0;
  2725. }
  2726. /** Unregister a previously registered membership. This prevents dropping the membership
  2727. * on socket close.
  2728. *
  2729. * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
  2730. */
  2731. static void
  2732. lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
  2733. {
  2734. /* s+1 is stored in the array to prevent having to initialize the array
  2735. (default initialization is to 0) */
  2736. int sa = s + 1;
  2737. int i;
  2738. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2739. if ((socket_ipv4_multicast_memberships[i].sa == sa) &&
  2740. ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
  2741. ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
  2742. socket_ipv4_multicast_memberships[i].sa = 0;
  2743. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
  2744. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
  2745. return;
  2746. }
  2747. }
  2748. }
  2749. /** Drop all memberships of a socket that were not dropped explicitly via setsockopt.
  2750. *
  2751. * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK).
  2752. */
  2753. static void lwip_socket_drop_registered_memberships(int s)
  2754. {
  2755. /* s+1 is stored in the array to prevent having to initialize the array
  2756. (default initialization is to 0) */
  2757. int sa = s + 1;
  2758. int i;
  2759. LWIP_ASSERT("socket has no netconn", sockets[s].conn != NULL);
  2760. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2761. if (socket_ipv4_multicast_memberships[i].sa == sa) {
  2762. ip_addr_t multi_addr, if_addr;
  2763. ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
  2764. ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
  2765. socket_ipv4_multicast_memberships[i].sa = 0;
  2766. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
  2767. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
  2768. netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE);
  2769. }
  2770. }
  2771. }
  2772. #endif /* LWIP_IGMP */
  2773. #if ESP_THREAD_SAFE
  2774. int
  2775. lwip_sendto_r(int s, const void *data, size_t size, int flags,
  2776. const struct sockaddr *to, socklen_t tolen)
  2777. {
  2778. LWIP_API_LOCK();
  2779. __ret = lwip_sendto(s, data, size, flags, to, tolen);
  2780. LWIP_API_UNLOCK();
  2781. }
  2782. int
  2783. lwip_send_r(int s, const void *data, size_t size, int flags)
  2784. {
  2785. LWIP_API_LOCK();
  2786. __ret = lwip_send(s, data, size, flags);
  2787. LWIP_API_UNLOCK();
  2788. }
  2789. int
  2790. lwip_recvfrom_r(int s, void *mem, size_t len, int flags,
  2791. struct sockaddr *from, socklen_t *fromlen)
  2792. {
  2793. LWIP_API_LOCK();
  2794. __ret = lwip_recvfrom(s, mem, len, flags, from, fromlen);
  2795. LWIP_API_UNLOCK();
  2796. }
  2797. int
  2798. lwip_recv_r(int s, void *mem, size_t len, int flags)
  2799. {
  2800. return lwip_recvfrom_r(s, mem, len, flags, NULL, NULL);
  2801. }
  2802. int
  2803. lwip_read_r(int s, void *mem, size_t len)
  2804. {
  2805. return lwip_recvfrom_r(s, mem, len, 0, NULL, NULL);
  2806. }
  2807. int
  2808. lwip_sendmsg_r(int s, const struct msghdr *msg, int flags)
  2809. {
  2810. LWIP_API_LOCK();
  2811. __ret = lwip_sendmsg(s, msg, flags);
  2812. LWIP_API_UNLOCK();
  2813. }
  2814. int
  2815. lwip_write_r(int s, const void *data, size_t size)
  2816. {
  2817. return lwip_send_r(s, data, size, 0);
  2818. }
  2819. int
  2820. lwip_writev_r(int s, const struct iovec *iov, int iovcnt)
  2821. {
  2822. struct msghdr msg;
  2823. msg.msg_name = NULL;
  2824. msg.msg_namelen = 0;
  2825. /* Hack: we have to cast via number to cast from 'const' pointer to non-const.
  2826. Blame the opengroup standard for this inconsistency. */
  2827. msg.msg_iov = (struct iovec *)(size_t)iov;
  2828. msg.msg_iovlen = iovcnt;
  2829. msg.msg_control = NULL;
  2830. msg.msg_controllen = 0;
  2831. msg.msg_flags = 0;
  2832. return lwip_sendmsg_r(s, &msg, 0);
  2833. }
  2834. int
  2835. lwip_connect_r(int s, const struct sockaddr *name, socklen_t namelen)
  2836. {
  2837. LWIP_API_LOCK();
  2838. __ret = lwip_connect(s, name, namelen);
  2839. LWIP_API_UNLOCK();
  2840. }
  2841. int
  2842. lwip_listen_r(int s, int backlog)
  2843. {
  2844. LWIP_API_LOCK();
  2845. __ret = lwip_listen(s, backlog);
  2846. LWIP_API_UNLOCK();
  2847. }
  2848. int
  2849. lwip_bind_r(int s, const struct sockaddr *name, socklen_t namelen)
  2850. {
  2851. LWIP_API_LOCK();
  2852. __ret = lwip_bind(s, name, namelen);
  2853. LWIP_API_UNLOCK();
  2854. }
  2855. int
  2856. lwip_accept_r(int s, struct sockaddr *addr, socklen_t *addrlen)
  2857. {
  2858. LWIP_API_LOCK();
  2859. __ret = lwip_accept(s, addr, addrlen);
  2860. LWIP_API_UNLOCK();
  2861. }
  2862. int
  2863. lwip_ioctl_r(int s, long cmd, void *argp)
  2864. {
  2865. LWIP_API_LOCK();
  2866. __ret = lwip_ioctl(s, cmd, argp);
  2867. LWIP_API_UNLOCK();
  2868. }
  2869. int
  2870. lwip_fcntl_r(int s, int cmd, int val)
  2871. {
  2872. LWIP_API_LOCK();
  2873. __ret = lwip_fcntl(s, cmd, val);
  2874. LWIP_API_UNLOCK();
  2875. }
  2876. int
  2877. lwip_setsockopt_r(int s, int level, int optname, const void *optval, socklen_t optlen)
  2878. {
  2879. LWIP_API_LOCK();
  2880. __ret = lwip_setsockopt(s, level, optname, optval, optlen);
  2881. LWIP_API_UNLOCK();
  2882. }
  2883. int
  2884. lwip_getsockopt_r(int s, int level, int optname, void *optval, socklen_t *optlen)
  2885. {
  2886. LWIP_API_LOCK();
  2887. __ret = lwip_getsockopt(s, level, optname, optval, optlen);
  2888. LWIP_API_UNLOCK();
  2889. }
  2890. int
  2891. lwip_getpeername_r(int s, struct sockaddr *name, socklen_t *namelen)
  2892. {
  2893. LWIP_API_LOCK();
  2894. __ret = lwip_getpeername(s, name, namelen);
  2895. LWIP_API_UNLOCK();
  2896. }
  2897. int
  2898. lwip_getsockname_r(int s, struct sockaddr *name, socklen_t *namelen)
  2899. {
  2900. LWIP_API_LOCK();
  2901. __ret = lwip_getsockname(s, name, namelen);
  2902. LWIP_API_UNLOCK();
  2903. }
  2904. int
  2905. lwip_close_r(int s)
  2906. {
  2907. LWIP_API_LOCK();
  2908. LWIP_SET_CLOSE_FLAG();
  2909. __ret = lwip_close(s);
  2910. LWIP_API_UNLOCK();
  2911. }
  2912. int
  2913. lwip_shutdown_r(int s, int how)
  2914. {
  2915. LWIP_API_LOCK();
  2916. __ret = lwip_shutdown(s, how);
  2917. LWIP_API_UNLOCK();
  2918. }
  2919. #endif
  2920. #endif /* LWIP_SOCKET */