sockets.c 105 KB

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