modusocket.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. * Copyright (c) 2015 Daniel Campora
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdint.h>
  28. #include <string.h>
  29. #include "simplelink.h"
  30. #include "py/mpconfig.h"
  31. #include "py/obj.h"
  32. #include "py/objstr.h"
  33. #include "py/runtime.h"
  34. #include "py/stream.h"
  35. #include "py/mphal.h"
  36. #include "lib/netutils/netutils.h"
  37. #include "modnetwork.h"
  38. #include "modusocket.h"
  39. #include "mpexception.h"
  40. /******************************************************************************/
  41. // The following set of macros and functions provide a glue between the CC3100
  42. // simplelink layer and the functions/methods provided by the usocket module.
  43. // They were historically in a separate file because usocket was designed to
  44. // work with multiple NICs, and the wlan_XXX functions just provided one
  45. // particular NIC implementation (that of the CC3100). But the CC3200 port only
  46. // supports a single NIC (being the CC3100) so it's unnecessary and inefficient
  47. // to provide an intermediate wrapper layer. Hence the wlan_XXX functions
  48. // are provided below as static functions so they can be inlined directly by
  49. // the corresponding usocket calls.
  50. #define WLAN_MAX_RX_SIZE 16000
  51. #define WLAN_MAX_TX_SIZE 1476
  52. #define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \
  53. addr.sa_family = SL_AF_INET; \
  54. addr.sa_data[0] = port >> 8; \
  55. addr.sa_data[1] = port; \
  56. addr.sa_data[2] = ip[3]; \
  57. addr.sa_data[3] = ip[2]; \
  58. addr.sa_data[4] = ip[1]; \
  59. addr.sa_data[5] = ip[0];
  60. #define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
  61. ip[0] = addr.sa_data[5]; \
  62. ip[1] = addr.sa_data[4]; \
  63. ip[2] = addr.sa_data[3]; \
  64. ip[3] = addr.sa_data[2];
  65. #define SOCKET_TIMEOUT_QUANTA_MS (20)
  66. STATIC int convert_sl_errno(int sl_errno) {
  67. return -sl_errno;
  68. }
  69. // This function is left as non-static so it's not inlined.
  70. int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) {
  71. if (*timeout_ms == 0 || ret != SL_EAGAIN) {
  72. if (s->sock_base.timeout_ms > 0 && ret == SL_EAGAIN) {
  73. *_errno = MP_ETIMEDOUT;
  74. } else {
  75. *_errno = convert_sl_errno(ret);
  76. }
  77. return -1;
  78. }
  79. mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS);
  80. if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) {
  81. *timeout_ms = 0;
  82. } else {
  83. *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS;
  84. }
  85. return 0;
  86. }
  87. STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
  88. uint32_t ip;
  89. int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
  90. out_ip[0] = ip;
  91. out_ip[1] = ip >> 8;
  92. out_ip[2] = ip >> 16;
  93. out_ip[3] = ip >> 24;
  94. return result;
  95. }
  96. STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
  97. int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto);
  98. if (sd < 0) {
  99. *_errno = sd;
  100. return -1;
  101. }
  102. s->sock_base.sd = sd;
  103. return 0;
  104. }
  105. STATIC void wlan_socket_close(mod_network_socket_obj_t *s) {
  106. // this is to prevent the finalizer to close a socket that failed when being created
  107. if (s->sock_base.sd >= 0) {
  108. modusocket_socket_delete(s->sock_base.sd);
  109. sl_Close(s->sock_base.sd);
  110. s->sock_base.sd = -1;
  111. }
  112. }
  113. STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
  114. MAKE_SOCKADDR(addr, ip, port)
  115. int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr));
  116. if (ret != 0) {
  117. *_errno = ret;
  118. return -1;
  119. }
  120. return 0;
  121. }
  122. STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
  123. int ret = sl_Listen(s->sock_base.sd, backlog);
  124. if (ret != 0) {
  125. *_errno = ret;
  126. return -1;
  127. }
  128. return 0;
  129. }
  130. STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
  131. // accept incoming connection
  132. int16_t sd;
  133. SlSockAddr_t addr;
  134. SlSocklen_t addr_len = sizeof(addr);
  135. uint32_t timeout_ms = s->sock_base.timeout_ms;
  136. for (;;) {
  137. sd = sl_Accept(s->sock_base.sd, &addr, &addr_len);
  138. if (sd >= 0) {
  139. // save the socket descriptor
  140. s2->sock_base.sd = sd;
  141. // return ip and port
  142. UNPACK_SOCKADDR(addr, ip, *port);
  143. return 0;
  144. }
  145. if (check_timedout(s, sd, &timeout_ms, _errno)) {
  146. return -1;
  147. }
  148. }
  149. }
  150. STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
  151. MAKE_SOCKADDR(addr, ip, port)
  152. uint32_t timeout_ms = s->sock_base.timeout_ms;
  153. // For a non-blocking connect the CC3100 will return SL_EALREADY while the
  154. // connection is in progress.
  155. for (;;) {
  156. int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr));
  157. if (ret == 0) {
  158. return 0;
  159. }
  160. // Check if we are in non-blocking mode and the connection is in progress
  161. if (s->sock_base.timeout_ms == 0 && ret == SL_EALREADY) {
  162. // To match BSD we return EINPROGRESS here
  163. *_errno = MP_EINPROGRESS;
  164. return -1;
  165. }
  166. // We are in blocking mode, so if the connection isn't in progress then error out
  167. if (ret != SL_EALREADY) {
  168. *_errno = convert_sl_errno(ret);
  169. return -1;
  170. }
  171. if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) {
  172. return -1;
  173. }
  174. }
  175. }
  176. STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
  177. if (len == 0) {
  178. return 0;
  179. }
  180. uint32_t timeout_ms = s->sock_base.timeout_ms;
  181. for (;;) {
  182. int ret = sl_Send(s->sock_base.sd, (const void *)buf, len, 0);
  183. if (ret > 0) {
  184. return ret;
  185. }
  186. if (check_timedout(s, ret, &timeout_ms, _errno)) {
  187. return -1;
  188. }
  189. }
  190. }
  191. STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
  192. uint32_t timeout_ms = s->sock_base.timeout_ms;
  193. for (;;) {
  194. int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
  195. if (ret >= 0) {
  196. return ret;
  197. }
  198. if (check_timedout(s, ret, &timeout_ms, _errno)) {
  199. return -1;
  200. }
  201. }
  202. }
  203. STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
  204. MAKE_SOCKADDR(addr, ip, port)
  205. uint32_t timeout_ms = s->sock_base.timeout_ms;
  206. for (;;) {
  207. int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr));
  208. if (ret >= 0) {
  209. return ret;
  210. }
  211. if (check_timedout(s, ret, &timeout_ms, _errno)) {
  212. return -1;
  213. }
  214. }
  215. }
  216. STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
  217. SlSockAddr_t addr;
  218. SlSocklen_t addr_len = sizeof(addr);
  219. uint32_t timeout_ms = s->sock_base.timeout_ms;
  220. for (;;) {
  221. int ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
  222. if (ret >= 0) {
  223. UNPACK_SOCKADDR(addr, ip, *port);
  224. return ret;
  225. }
  226. if (check_timedout(s, ret, &timeout_ms, _errno)) {
  227. return -1;
  228. }
  229. }
  230. }
  231. STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
  232. int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen);
  233. if (ret < 0) {
  234. *_errno = ret;
  235. return -1;
  236. }
  237. return 0;
  238. }
  239. STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) {
  240. SlSockNonblocking_t option;
  241. if (timeout_s == 0 || timeout_s == -1) {
  242. if (timeout_s == 0) {
  243. // set non-blocking mode
  244. option.NonblockingEnabled = 1;
  245. } else {
  246. // set blocking mode
  247. option.NonblockingEnabled = 0;
  248. }
  249. timeout_s = 0;
  250. } else {
  251. // synthesize timeout via non-blocking behaviour with a loop
  252. option.NonblockingEnabled = 1;
  253. }
  254. int ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option));
  255. if (ret != 0) {
  256. *_errno = convert_sl_errno(ret);
  257. return -1;
  258. }
  259. s->sock_base.timeout_ms = timeout_s * 1000;
  260. return 0;
  261. }
  262. STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
  263. mp_int_t ret;
  264. if (request == MP_STREAM_POLL) {
  265. mp_uint_t flags = arg;
  266. ret = 0;
  267. int32_t sd = s->sock_base.sd;
  268. // init fds
  269. SlFdSet_t rfds, wfds, xfds;
  270. SL_FD_ZERO(&rfds);
  271. SL_FD_ZERO(&wfds);
  272. SL_FD_ZERO(&xfds);
  273. // set fds if needed
  274. if (flags & MP_STREAM_POLL_RD) {
  275. SL_FD_SET(sd, &rfds);
  276. }
  277. if (flags & MP_STREAM_POLL_WR) {
  278. SL_FD_SET(sd, &wfds);
  279. }
  280. if (flags & MP_STREAM_POLL_HUP) {
  281. SL_FD_SET(sd, &xfds);
  282. }
  283. // call simplelink's select with minimum timeout
  284. SlTimeval_t tv;
  285. tv.tv_sec = 0;
  286. tv.tv_usec = 1;
  287. int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
  288. // check for errors
  289. if (nfds == -1) {
  290. *_errno = nfds;
  291. return -1;
  292. }
  293. // check return of select
  294. if (SL_FD_ISSET(sd, &rfds)) {
  295. ret |= MP_STREAM_POLL_RD;
  296. }
  297. if (SL_FD_ISSET(sd, &wfds)) {
  298. ret |= MP_STREAM_POLL_WR;
  299. }
  300. if (SL_FD_ISSET(sd, &xfds)) {
  301. ret |= MP_STREAM_POLL_HUP;
  302. }
  303. } else if (request == MP_STREAM_CLOSE) {
  304. wlan_socket_close(s);
  305. ret = 0;
  306. } else {
  307. *_errno = MP_EINVAL;
  308. ret = MP_STREAM_ERROR;
  309. }
  310. return ret;
  311. }
  312. /******************************************************************************
  313. DEFINE PRIVATE CONSTANTS
  314. ******************************************************************************/
  315. #define MOD_NETWORK_MAX_SOCKETS 10
  316. /******************************************************************************
  317. DEFINE PRIVATE TYPES
  318. ******************************************************************************/
  319. typedef struct {
  320. int16_t sd;
  321. bool user;
  322. } modusocket_sock_t;
  323. /******************************************************************************
  324. DEFINE PRIVATE DATA
  325. ******************************************************************************/
  326. STATIC const mp_obj_type_t socket_type;
  327. STATIC OsiLockObj_t modusocket_LockObj;
  328. STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1},
  329. {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}};
  330. /******************************************************************************
  331. DEFINE PUBLIC FUNCTIONS
  332. ******************************************************************************/
  333. __attribute__ ((section (".boot")))
  334. void modusocket_pre_init (void) {
  335. // create the wlan lock
  336. ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock"));
  337. sl_LockObjUnlock (&modusocket_LockObj);
  338. }
  339. void modusocket_socket_add (int16_t sd, bool user) {
  340. sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
  341. for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
  342. if (modusocket_sockets[i].sd < 0) {
  343. modusocket_sockets[i].sd = sd;
  344. modusocket_sockets[i].user = user;
  345. break;
  346. }
  347. }
  348. sl_LockObjUnlock (&modusocket_LockObj);
  349. }
  350. void modusocket_socket_delete (int16_t sd) {
  351. sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
  352. for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
  353. if (modusocket_sockets[i].sd == sd) {
  354. modusocket_sockets[i].sd = -1;
  355. break;
  356. }
  357. }
  358. sl_LockObjUnlock (&modusocket_LockObj);
  359. }
  360. void modusocket_enter_sleep (void) {
  361. SlFdSet_t socketset;
  362. int16_t maxfd = 0;
  363. for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
  364. int16_t sd;
  365. if ((sd = modusocket_sockets[i].sd) >= 0) {
  366. SL_FD_SET(sd, &socketset);
  367. maxfd = (maxfd > sd) ? maxfd : sd;
  368. }
  369. }
  370. if (maxfd > 0) {
  371. // wait for any of the sockets to become ready...
  372. sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
  373. }
  374. }
  375. void modusocket_close_all_user_sockets (void) {
  376. sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
  377. for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
  378. if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) {
  379. sl_Close(modusocket_sockets[i].sd);
  380. modusocket_sockets[i].sd = -1;
  381. }
  382. }
  383. sl_LockObjUnlock (&modusocket_LockObj);
  384. }
  385. /******************************************************************************/
  386. // socket class
  387. // constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
  388. STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  389. mp_arg_check_num(n_args, n_kw, 0, 4, false);
  390. // create socket object
  391. mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
  392. s->base.type = (mp_obj_t)&socket_type;
  393. s->sock_base.u_param.domain = SL_AF_INET;
  394. s->sock_base.u_param.type = SL_SOCK_STREAM;
  395. s->sock_base.u_param.proto = SL_IPPROTO_TCP;
  396. s->sock_base.u_param.fileno = -1;
  397. s->sock_base.timeout_ms = 0;
  398. s->sock_base.cert_req = false;
  399. if (n_args > 0) {
  400. s->sock_base.u_param.domain = mp_obj_get_int(args[0]);
  401. if (n_args > 1) {
  402. s->sock_base.u_param.type = mp_obj_get_int(args[1]);
  403. if (n_args > 2) {
  404. s->sock_base.u_param.proto = mp_obj_get_int(args[2]);
  405. if (n_args > 3) {
  406. s->sock_base.u_param.fileno = mp_obj_get_int(args[3]);
  407. }
  408. }
  409. }
  410. }
  411. // create the socket
  412. int _errno;
  413. if (wlan_socket_socket(s, &_errno) != 0) {
  414. mp_raise_OSError(-_errno);
  415. }
  416. // add the socket to the list
  417. modusocket_socket_add(s->sock_base.sd, true);
  418. return s;
  419. }
  420. // method socket.bind(address)
  421. STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
  422. mod_network_socket_obj_t *self = self_in;
  423. // get address
  424. uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
  425. mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
  426. // call the NIC to bind the socket
  427. int _errno = 0;
  428. if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
  429. mp_raise_OSError(-_errno);
  430. }
  431. return mp_const_none;
  432. }
  433. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
  434. // method socket.listen([backlog])
  435. STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) {
  436. mod_network_socket_obj_t *self = args[0];
  437. int32_t backlog = 0;
  438. if (n_args > 1) {
  439. backlog = mp_obj_get_int(args[1]);
  440. backlog = (backlog < 0) ? 0 : backlog;
  441. }
  442. int _errno;
  443. if (wlan_socket_listen(self, backlog, &_errno) != 0) {
  444. mp_raise_OSError(-_errno);
  445. }
  446. return mp_const_none;
  447. }
  448. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen);
  449. // method socket.accept()
  450. STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
  451. mod_network_socket_obj_t *self = self_in;
  452. // create new socket object
  453. mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
  454. // the new socket inherits all properties from its parent
  455. memcpy (socket2, self, sizeof(mod_network_socket_obj_t));
  456. // accept the incoming connection
  457. uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
  458. mp_uint_t port = 0;
  459. int _errno = 0;
  460. if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
  461. mp_raise_OSError(_errno);
  462. }
  463. // add the socket to the list
  464. modusocket_socket_add(socket2->sock_base.sd, true);
  465. // make the return value
  466. mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
  467. client->items[0] = socket2;
  468. client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE);
  469. return client;
  470. }
  471. STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
  472. // method socket.connect(address)
  473. STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
  474. mod_network_socket_obj_t *self = self_in;
  475. // get address
  476. uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
  477. mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
  478. // connect the socket
  479. int _errno;
  480. if (wlan_socket_connect(self, ip, port, &_errno) != 0) {
  481. if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) {
  482. return mp_const_none;
  483. }
  484. mp_raise_OSError(_errno);
  485. }
  486. return mp_const_none;
  487. }
  488. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
  489. // method socket.send(bytes)
  490. STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
  491. mod_network_socket_obj_t *self = self_in;
  492. mp_buffer_info_t bufinfo;
  493. mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
  494. int _errno;
  495. mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno);
  496. if (ret < 0) {
  497. mp_raise_OSError(_errno);
  498. }
  499. return mp_obj_new_int_from_uint(ret);
  500. }
  501. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
  502. // method socket.recv(bufsize)
  503. STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
  504. mod_network_socket_obj_t *self = self_in;
  505. mp_int_t len = mp_obj_get_int(len_in);
  506. vstr_t vstr;
  507. vstr_init_len(&vstr, len);
  508. int _errno;
  509. mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
  510. if (ret < 0) {
  511. mp_raise_OSError(_errno);
  512. }
  513. if (ret == 0) {
  514. return mp_const_empty_bytes;
  515. }
  516. vstr.len = ret;
  517. vstr.buf[vstr.len] = '\0';
  518. return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
  519. }
  520. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
  521. // method socket.sendto(bytes, address)
  522. STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
  523. mod_network_socket_obj_t *self = self_in;
  524. // get the data
  525. mp_buffer_info_t bufinfo;
  526. mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
  527. // get address
  528. uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
  529. mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
  530. // call the nic to sendto
  531. int _errno = 0;
  532. mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
  533. if (ret < 0) {
  534. mp_raise_OSError(_errno);
  535. }
  536. return mp_obj_new_int(ret);
  537. }
  538. STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
  539. // method socket.recvfrom(bufsize)
  540. STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
  541. mod_network_socket_obj_t *self = self_in;
  542. vstr_t vstr;
  543. vstr_init_len(&vstr, mp_obj_get_int(len_in));
  544. byte ip[4];
  545. mp_uint_t port = 0;
  546. int _errno = 0;
  547. mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
  548. if (ret < 0) {
  549. mp_raise_OSError(_errno);
  550. }
  551. mp_obj_t tuple[2];
  552. if (ret == 0) {
  553. tuple[0] = mp_const_empty_bytes;
  554. } else {
  555. vstr.len = ret;
  556. vstr.buf[vstr.len] = '\0';
  557. tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
  558. }
  559. tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE);
  560. return mp_obj_new_tuple(2, tuple);
  561. }
  562. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
  563. // method socket.setsockopt(level, optname, value)
  564. STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
  565. mod_network_socket_obj_t *self = args[0];
  566. mp_int_t level = mp_obj_get_int(args[1]);
  567. mp_int_t opt = mp_obj_get_int(args[2]);
  568. const void *optval;
  569. mp_uint_t optlen;
  570. mp_int_t val;
  571. if (mp_obj_is_integer(args[3])) {
  572. val = mp_obj_get_int_truncated(args[3]);
  573. optval = &val;
  574. optlen = sizeof(val);
  575. } else {
  576. mp_buffer_info_t bufinfo;
  577. mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
  578. optval = bufinfo.buf;
  579. optlen = bufinfo.len;
  580. }
  581. int _errno;
  582. if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
  583. mp_raise_OSError(-_errno);
  584. }
  585. return mp_const_none;
  586. }
  587. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
  588. // method socket.settimeout(value)
  589. // timeout=0 means non-blocking
  590. // timeout=None means blocking
  591. // otherwise, timeout is in seconds
  592. STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
  593. mod_network_socket_obj_t *self = self_in;
  594. mp_uint_t timeout;
  595. if (timeout_in == mp_const_none) {
  596. timeout = -1;
  597. } else {
  598. timeout = mp_obj_get_int(timeout_in);
  599. }
  600. int _errno = 0;
  601. if (wlan_socket_settimeout(self, timeout, &_errno) != 0) {
  602. mp_raise_OSError(_errno);
  603. }
  604. return mp_const_none;
  605. }
  606. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
  607. // method socket.setblocking(flag)
  608. STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
  609. if (mp_obj_is_true(blocking)) {
  610. return socket_settimeout(self_in, mp_const_none);
  611. } else {
  612. return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0));
  613. }
  614. }
  615. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
  616. STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
  617. (void)n_args;
  618. return args[0];
  619. }
  620. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile);
  621. STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
  622. { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
  623. { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
  624. { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
  625. { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
  626. { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
  627. { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
  628. { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
  629. { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_send_obj) },
  630. { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
  631. { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
  632. { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
  633. { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
  634. { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
  635. { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
  636. { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) },
  637. // stream methods
  638. { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) },
  639. { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
  640. { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
  641. { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
  642. };
  643. MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
  644. STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
  645. mod_network_socket_obj_t *self = self_in;
  646. mp_int_t ret = wlan_socket_recv(self, buf, size, errcode);
  647. if (ret < 0) {
  648. // we need to ignore the socket closed error here because a read() without params
  649. // only returns when the socket is closed by the other end
  650. if (*errcode != -SL_ESECCLOSED) {
  651. ret = MP_STREAM_ERROR;
  652. } else {
  653. ret = 0;
  654. }
  655. }
  656. return ret;
  657. }
  658. STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
  659. mod_network_socket_obj_t *self = self_in;
  660. mp_int_t ret = wlan_socket_send(self, buf, size, errcode);
  661. if (ret < 0) {
  662. ret = MP_STREAM_ERROR;
  663. }
  664. return ret;
  665. }
  666. STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
  667. mod_network_socket_obj_t *self = self_in;
  668. return wlan_socket_ioctl(self, request, arg, errcode);
  669. }
  670. const mp_stream_p_t socket_stream_p = {
  671. .read = socket_read,
  672. .write = socket_write,
  673. .ioctl = socket_ioctl,
  674. .is_text = false,
  675. };
  676. STATIC const mp_obj_type_t socket_type = {
  677. { &mp_type_type },
  678. .name = MP_QSTR_socket,
  679. .make_new = socket_make_new,
  680. .protocol = &socket_stream_p,
  681. .locals_dict = (mp_obj_t)&socket_locals_dict,
  682. };
  683. /******************************************************************************/
  684. // usocket module
  685. // function usocket.getaddrinfo(host, port)
  686. /// \function getaddrinfo(host, port)
  687. STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
  688. size_t hlen;
  689. const char *host = mp_obj_str_get_data(host_in, &hlen);
  690. mp_int_t port = mp_obj_get_int(port_in);
  691. // ipv4 only
  692. uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
  693. int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET);
  694. if (result < 0) {
  695. mp_raise_OSError(-result);
  696. }
  697. mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
  698. tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET);
  699. tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM);
  700. tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
  701. tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
  702. tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
  703. return mp_obj_new_list(1, (mp_obj_t*)&tuple);
  704. }
  705. STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo);
  706. STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = {
  707. { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
  708. { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
  709. { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) },
  710. // class constants
  711. { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(SL_AF_INET) },
  712. { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SL_SOCK_STREAM) },
  713. { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SL_SOCK_DGRAM) },
  714. { MP_ROM_QSTR(MP_QSTR_IPPROTO_SEC), MP_ROM_INT(SL_SEC_SOCKET) },
  715. { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(SL_IPPROTO_TCP) },
  716. { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(SL_IPPROTO_UDP) },
  717. };
  718. STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
  719. const mp_obj_module_t mp_module_usocket = {
  720. .base = { &mp_type_module },
  721. .globals = (mp_obj_dict_t*)&mp_module_usocket_globals,
  722. };