modusocket.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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) 2014 Paul Sokolovsky
  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 <stdio.h>
  28. #include <assert.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <sys/stat.h>
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <netinet/in.h>
  36. #include <arpa/inet.h>
  37. #include <netdb.h>
  38. #include <errno.h>
  39. #include "py/objtuple.h"
  40. #include "py/objstr.h"
  41. #include "py/runtime.h"
  42. #include "py/stream.h"
  43. #include "py/builtin.h"
  44. #include "py/mphal.h"
  45. /*
  46. The idea of this module is to implement reasonable minimum of
  47. socket-related functions to write typical clients and servers.
  48. The module named "usocket" on purpose, to allow to make
  49. Python-level module more (or fully) compatible with CPython
  50. "socket", e.g.:
  51. ---- socket.py ----
  52. from usocket import *
  53. from socket_more_funcs import *
  54. from socket_more_funcs2 import *
  55. -------------------
  56. I.e. this module should stay lean, and more functions (if needed)
  57. should be add to separate modules (C or Python level).
  58. */
  59. // This type must "inherit" from mp_obj_fdfile_t, i.e. matching subset of
  60. // fields should have the same layout.
  61. typedef struct _mp_obj_socket_t {
  62. mp_obj_base_t base;
  63. int fd;
  64. } mp_obj_socket_t;
  65. const mp_obj_type_t mp_type_socket;
  66. // Helper functions
  67. static inline mp_obj_t mp_obj_from_sockaddr(const struct sockaddr *addr, socklen_t len) {
  68. return mp_obj_new_bytes((const byte *)addr, len);
  69. }
  70. STATIC mp_obj_socket_t *socket_new(int fd) {
  71. mp_obj_socket_t *o = m_new_obj(mp_obj_socket_t);
  72. o->base.type = &mp_type_socket;
  73. o->fd = fd;
  74. return o;
  75. }
  76. STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
  77. (void)kind;
  78. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  79. mp_printf(print, "<_socket %d>", self->fd);
  80. }
  81. STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
  82. mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
  83. mp_int_t r = read(o->fd, buf, size);
  84. if (r == -1) {
  85. *errcode = errno;
  86. return MP_STREAM_ERROR;
  87. }
  88. return r;
  89. }
  90. STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
  91. mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
  92. mp_int_t r = write(o->fd, buf, size);
  93. if (r == -1) {
  94. *errcode = errno;
  95. return MP_STREAM_ERROR;
  96. }
  97. return r;
  98. }
  99. STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
  100. mp_obj_socket_t *self = MP_OBJ_TO_PTR(o_in);
  101. (void)arg;
  102. switch (request) {
  103. case MP_STREAM_CLOSE:
  104. // There's a POSIX drama regarding return value of close in general,
  105. // and EINTR error in particular. See e.g.
  106. // http://lwn.net/Articles/576478/
  107. // http://austingroupbugs.net/view.php?id=529
  108. // The rationale MicroPython follows is that close() just releases
  109. // file descriptor. If you're interested to catch I/O errors before
  110. // closing fd, fsync() it.
  111. close(self->fd);
  112. return 0;
  113. case MP_STREAM_GET_FILENO:
  114. return self->fd;
  115. default:
  116. *errcode = MP_EINVAL;
  117. return MP_STREAM_ERROR;
  118. }
  119. }
  120. STATIC mp_obj_t socket_fileno(mp_obj_t self_in) {
  121. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  122. return MP_OBJ_NEW_SMALL_INT(self->fd);
  123. }
  124. STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
  125. STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
  126. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  127. mp_buffer_info_t bufinfo;
  128. mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ);
  129. int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
  130. RAISE_ERRNO(r, errno);
  131. return mp_const_none;
  132. }
  133. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
  134. STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
  135. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  136. mp_buffer_info_t bufinfo;
  137. mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ);
  138. int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
  139. RAISE_ERRNO(r, errno);
  140. return mp_const_none;
  141. }
  142. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
  143. STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
  144. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  145. int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in));
  146. RAISE_ERRNO(r, errno);
  147. return mp_const_none;
  148. }
  149. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
  150. STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
  151. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  152. // sockaddr_storage isn't stack-friendly (129 bytes or so)
  153. //struct sockaddr_storage addr;
  154. byte addr[32];
  155. socklen_t addr_len = sizeof(addr);
  156. int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len);
  157. RAISE_ERRNO(fd, errno);
  158. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
  159. t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd));
  160. t->items[1] = mp_obj_new_bytearray(addr_len, &addr);
  161. return MP_OBJ_FROM_PTR(t);
  162. }
  163. STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
  164. // Note: besides flag param, this differs from read() in that
  165. // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) -
  166. // these would be thrown as exceptions.
  167. STATIC mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) {
  168. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  169. int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
  170. int flags = 0;
  171. if (n_args > 2) {
  172. flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
  173. }
  174. byte *buf = m_new(byte, sz);
  175. int out_sz = recv(self->fd, buf, sz, flags);
  176. RAISE_ERRNO(out_sz, errno);
  177. mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
  178. m_del(char, buf, sz);
  179. return ret;
  180. }
  181. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv);
  182. STATIC mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) {
  183. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  184. int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
  185. int flags = 0;
  186. if (n_args > 2) {
  187. flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
  188. }
  189. struct sockaddr_storage addr;
  190. socklen_t addr_len = sizeof(addr);
  191. byte *buf = m_new(byte, sz);
  192. int out_sz = recvfrom(self->fd, buf, sz, flags, (struct sockaddr*)&addr, &addr_len);
  193. RAISE_ERRNO(out_sz, errno);
  194. mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
  195. m_del(char, buf, sz);
  196. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
  197. t->items[0] = buf_o;
  198. t->items[1] = mp_obj_from_sockaddr((struct sockaddr*)&addr, addr_len);
  199. return MP_OBJ_FROM_PTR(t);
  200. }
  201. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recvfrom_obj, 2, 3, socket_recvfrom);
  202. // Note: besides flag param, this differs from write() in that
  203. // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) -
  204. // these would be thrown as exceptions.
  205. STATIC mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) {
  206. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  207. int flags = 0;
  208. if (n_args > 2) {
  209. flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
  210. }
  211. mp_buffer_info_t bufinfo;
  212. mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
  213. int out_sz = send(self->fd, bufinfo.buf, bufinfo.len, flags);
  214. RAISE_ERRNO(out_sz, errno);
  215. return MP_OBJ_NEW_SMALL_INT(out_sz);
  216. }
  217. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send);
  218. STATIC mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) {
  219. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  220. int flags = 0;
  221. mp_obj_t dst_addr = args[2];
  222. if (n_args > 3) {
  223. flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
  224. dst_addr = args[3];
  225. }
  226. mp_buffer_info_t bufinfo, addr_bi;
  227. mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
  228. mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ);
  229. int out_sz = sendto(self->fd, bufinfo.buf, bufinfo.len, flags,
  230. (struct sockaddr *)addr_bi.buf, addr_bi.len);
  231. RAISE_ERRNO(out_sz, errno);
  232. return MP_OBJ_NEW_SMALL_INT(out_sz);
  233. }
  234. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_sendto_obj, 3, 4, socket_sendto);
  235. STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
  236. (void)n_args; // always 4
  237. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  238. int level = MP_OBJ_SMALL_INT_VALUE(args[1]);
  239. int option = mp_obj_get_int(args[2]);
  240. const void *optval;
  241. socklen_t optlen;
  242. int val;
  243. if (MP_OBJ_IS_INT(args[3])) {
  244. val = mp_obj_int_get_truncated(args[3]);
  245. optval = &val;
  246. optlen = sizeof(val);
  247. } else {
  248. mp_buffer_info_t bufinfo;
  249. mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
  250. optval = bufinfo.buf;
  251. optlen = bufinfo.len;
  252. }
  253. int r = setsockopt(self->fd, level, option, optval, optlen);
  254. RAISE_ERRNO(r, errno);
  255. return mp_const_none;
  256. }
  257. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
  258. STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
  259. mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
  260. int val = mp_obj_is_true(flag_in);
  261. int flags = fcntl(self->fd, F_GETFL, 0);
  262. RAISE_ERRNO(flags, errno);
  263. if (val) {
  264. flags &= ~O_NONBLOCK;
  265. } else {
  266. flags |= O_NONBLOCK;
  267. }
  268. flags = fcntl(self->fd, F_SETFL, flags);
  269. RAISE_ERRNO(flags, errno);
  270. return mp_const_none;
  271. }
  272. STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
  273. STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
  274. // TODO: CPython explicitly says that closing returned object doesn't close
  275. // the original socket (Python2 at all says that fd is dup()ed). But we
  276. // save on the bloat.
  277. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
  278. mp_obj_t *new_args = alloca(n_args * sizeof(mp_obj_t));
  279. memcpy(new_args + 1, args + 1, (n_args - 1) * sizeof(mp_obj_t));
  280. new_args[0] = MP_OBJ_NEW_SMALL_INT(self->fd);
  281. return mp_builtin_open(n_args, new_args, (mp_map_t*)&mp_const_empty_map);
  282. }
  283. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile);
  284. STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  285. (void)type_in;
  286. (void)n_kw;
  287. int family = AF_INET;
  288. int type = SOCK_STREAM;
  289. int proto = 0;
  290. if (n_args > 0) {
  291. assert(MP_OBJ_IS_SMALL_INT(args[0]));
  292. family = MP_OBJ_SMALL_INT_VALUE(args[0]);
  293. if (n_args > 1) {
  294. assert(MP_OBJ_IS_SMALL_INT(args[1]));
  295. type = MP_OBJ_SMALL_INT_VALUE(args[1]);
  296. if (n_args > 2) {
  297. assert(MP_OBJ_IS_SMALL_INT(args[2]));
  298. proto = MP_OBJ_SMALL_INT_VALUE(args[2]);
  299. }
  300. }
  301. }
  302. int fd = socket(family, type, proto);
  303. RAISE_ERRNO(fd, errno);
  304. return MP_OBJ_FROM_PTR(socket_new(fd));
  305. }
  306. STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = {
  307. { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) },
  308. { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) },
  309. { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
  310. { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
  311. { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
  312. { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
  313. { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
  314. { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
  315. { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
  316. { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
  317. { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
  318. { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
  319. { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
  320. { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
  321. { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
  322. { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
  323. { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
  324. };
  325. STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table);
  326. STATIC const mp_stream_p_t usocket_stream_p = {
  327. .read = socket_read,
  328. .write = socket_write,
  329. .ioctl = socket_ioctl,
  330. };
  331. const mp_obj_type_t mp_type_socket = {
  332. { &mp_type_type },
  333. .name = MP_QSTR_socket,
  334. .print = socket_print,
  335. .make_new = socket_make_new,
  336. .getiter = NULL,
  337. .iternext = NULL,
  338. .protocol = &usocket_stream_p,
  339. .locals_dict = (mp_obj_dict_t*)&usocket_locals_dict,
  340. };
  341. #define BINADDR_MAX_LEN sizeof(struct in6_addr)
  342. STATIC mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) {
  343. int family = mp_obj_get_int(family_in);
  344. byte binaddr[BINADDR_MAX_LEN];
  345. int r = inet_pton(family, mp_obj_str_get_str(addr_in), binaddr);
  346. RAISE_ERRNO(r, errno);
  347. if (r == 0) {
  348. mp_raise_OSError(MP_EINVAL);
  349. }
  350. int binaddr_len = 0;
  351. switch (family) {
  352. case AF_INET:
  353. binaddr_len = sizeof(struct in_addr);
  354. break;
  355. case AF_INET6:
  356. binaddr_len = sizeof(struct in6_addr);
  357. break;
  358. }
  359. return mp_obj_new_bytes(binaddr, binaddr_len);
  360. }
  361. STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_pton_obj, mod_socket_inet_pton);
  362. STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) {
  363. int family = mp_obj_get_int(family_in);
  364. mp_buffer_info_t bufinfo;
  365. mp_get_buffer_raise(binaddr_in, &bufinfo, MP_BUFFER_READ);
  366. vstr_t vstr;
  367. vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
  368. if (inet_ntop(family, bufinfo.buf, vstr.buf, vstr.len) == NULL) {
  369. mp_raise_OSError(errno);
  370. }
  371. vstr.len = strlen(vstr.buf);
  372. return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
  373. }
  374. STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop);
  375. STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
  376. // TODO: Implement 5th and 6th args
  377. const char *host = mp_obj_str_get_str(args[0]);
  378. const char *serv = NULL;
  379. struct addrinfo hints;
  380. char buf[6];
  381. memset(&hints, 0, sizeof(hints));
  382. // getaddrinfo accepts port in string notation, so however
  383. // it may seem stupid, we need to convert int to str
  384. if (MP_OBJ_IS_SMALL_INT(args[1])) {
  385. unsigned port = (unsigned short)MP_OBJ_SMALL_INT_VALUE(args[1]);
  386. snprintf(buf, sizeof(buf), "%u", port);
  387. serv = buf;
  388. hints.ai_flags = AI_NUMERICSERV;
  389. #ifdef __UCLIBC_MAJOR__
  390. #if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32))
  391. // "warning" requires -Wno-cpp which is a relatively new gcc option, so we choose not to use it.
  392. //#warning Working around uClibc bug with numeric service name
  393. // Older versions og uClibc have bugs when numeric ports in service
  394. // arg require also hints.ai_socktype (or hints.ai_protocol) != 0
  395. // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to
  396. // test for that.
  397. // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5
  398. // Note that this is crude workaround, precluding UDP socket addresses
  399. // to be returned. TODO: set only if not set by Python args.
  400. hints.ai_socktype = SOCK_STREAM;
  401. #endif
  402. #endif
  403. } else {
  404. serv = mp_obj_str_get_str(args[1]);
  405. }
  406. if (n_args > 2) {
  407. hints.ai_family = MP_OBJ_SMALL_INT_VALUE(args[2]);
  408. if (n_args > 3) {
  409. hints.ai_socktype = MP_OBJ_SMALL_INT_VALUE(args[3]);
  410. }
  411. }
  412. struct addrinfo *addr_list;
  413. int res = getaddrinfo(host, serv, &hints, &addr_list);
  414. if (res != 0) {
  415. // CPython: socket.gaierror
  416. nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res));
  417. }
  418. assert(addr_list);
  419. mp_obj_t list = mp_obj_new_list(0, NULL);
  420. for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) {
  421. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
  422. t->items[0] = MP_OBJ_NEW_SMALL_INT(addr->ai_family);
  423. t->items[1] = MP_OBJ_NEW_SMALL_INT(addr->ai_socktype);
  424. t->items[2] = MP_OBJ_NEW_SMALL_INT(addr->ai_protocol);
  425. // "canonname will be a string representing the canonical name of the host
  426. // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ??
  427. if (addr->ai_canonname) {
  428. t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname));
  429. } else {
  430. t->items[3] = mp_const_none;
  431. }
  432. t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr);
  433. mp_obj_list_append(list, MP_OBJ_FROM_PTR(t));
  434. }
  435. freeaddrinfo(addr_list);
  436. return list;
  437. }
  438. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 4, mod_socket_getaddrinfo);
  439. STATIC mp_obj_t mod_socket_sockaddr(mp_obj_t sockaddr_in) {
  440. mp_buffer_info_t bufinfo;
  441. mp_get_buffer_raise(sockaddr_in, &bufinfo, MP_BUFFER_READ);
  442. switch (((struct sockaddr*)bufinfo.buf)->sa_family) {
  443. case AF_INET: {
  444. struct sockaddr_in *sa = (struct sockaddr_in*)bufinfo.buf;
  445. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
  446. t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
  447. t->items[1] = mp_obj_new_bytes((byte*)&sa->sin_addr, sizeof(sa->sin_addr));
  448. t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin_port));
  449. return MP_OBJ_FROM_PTR(t);
  450. }
  451. case AF_INET6: {
  452. struct sockaddr_in6 *sa = (struct sockaddr_in6*)bufinfo.buf;
  453. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
  454. t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET6);
  455. t->items[1] = mp_obj_new_bytes((byte*)&sa->sin6_addr, sizeof(sa->sin6_addr));
  456. t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin6_port));
  457. t->items[3] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_flowinfo));
  458. t->items[4] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_scope_id));
  459. return MP_OBJ_FROM_PTR(t);
  460. }
  461. default: {
  462. struct sockaddr *sa = (struct sockaddr*)bufinfo.buf;
  463. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
  464. t->items[0] = MP_OBJ_NEW_SMALL_INT(sa->sa_family);
  465. t->items[1] = mp_obj_new_bytes((byte*)sa->sa_data, bufinfo.len - offsetof(struct sockaddr, sa_data));
  466. return MP_OBJ_FROM_PTR(t);
  467. }
  468. }
  469. return mp_const_none;
  470. }
  471. STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_sockaddr_obj, mod_socket_sockaddr);
  472. STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
  473. { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
  474. { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_type_socket) },
  475. { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_socket_getaddrinfo_obj) },
  476. { MP_ROM_QSTR(MP_QSTR_inet_pton), MP_ROM_PTR(&mod_socket_inet_pton_obj) },
  477. { MP_ROM_QSTR(MP_QSTR_inet_ntop), MP_ROM_PTR(&mod_socket_inet_ntop_obj) },
  478. { MP_ROM_QSTR(MP_QSTR_sockaddr), MP_ROM_PTR(&mod_socket_sockaddr_obj) },
  479. #define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) }
  480. C(AF_UNIX),
  481. C(AF_INET),
  482. C(AF_INET6),
  483. C(SOCK_STREAM),
  484. C(SOCK_DGRAM),
  485. C(SOCK_RAW),
  486. C(MSG_DONTROUTE),
  487. C(MSG_DONTWAIT),
  488. C(SOL_SOCKET),
  489. C(SO_BROADCAST),
  490. C(SO_ERROR),
  491. C(SO_KEEPALIVE),
  492. C(SO_LINGER),
  493. C(SO_REUSEADDR),
  494. #undef C
  495. };
  496. STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table);
  497. const mp_obj_module_t mp_module_socket = {
  498. .base = { &mp_type_module },
  499. .globals = (mp_obj_dict_t*)&mp_module_socket_globals,
  500. };