sockets.c 102 KB

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