netutils.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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 <stdio.h>
  29. #include <string.h>
  30. #include "py/obj.h"
  31. #include "py/nlr.h"
  32. #include "py/runtime.h"
  33. #include "lib/netutils/netutils.h"
  34. // Takes an array with a raw IPv4 address and returns something like '192.168.0.1'.
  35. mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) {
  36. char ip_str[16];
  37. mp_uint_t ip_len;
  38. if (endian == NETUTILS_LITTLE) {
  39. ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
  40. } else {
  41. ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
  42. }
  43. return mp_obj_new_str(ip_str, ip_len, false);
  44. }
  45. // Takes an array with a raw IP address, and a port, and returns a net-address
  46. // tuple such as ('192.168.0.1', 8080).
  47. mp_obj_t netutils_format_inet_addr(uint8_t *ip, mp_uint_t port, netutils_endian_t endian) {
  48. mp_obj_t tuple[2] = {
  49. tuple[0] = netutils_format_ipv4_addr(ip, endian),
  50. tuple[1] = mp_obj_new_int(port),
  51. };
  52. return mp_obj_new_tuple(2, tuple);
  53. }
  54. void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
  55. size_t addr_len;
  56. const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
  57. if (addr_len == 0) {
  58. // special case of no address given
  59. memset(out_ip, 0, NETUTILS_IPV4ADDR_BUFSIZE);
  60. return;
  61. }
  62. const char *s = addr_str;
  63. const char *s_top = addr_str + addr_len;
  64. for (mp_uint_t i = 3 ; ; i--) {
  65. mp_uint_t val = 0;
  66. for (; s < s_top && *s != '.'; s++) {
  67. val = val * 10 + *s - '0';
  68. }
  69. if (endian == NETUTILS_LITTLE) {
  70. out_ip[i] = val;
  71. } else {
  72. out_ip[NETUTILS_IPV4ADDR_BUFSIZE - 1 - i] = val;
  73. }
  74. if (i == 0 && s == s_top) {
  75. return;
  76. } else if (i > 0 && s < s_top && *s == '.') {
  77. s++;
  78. } else {
  79. mp_raise_ValueError("invalid arguments");
  80. }
  81. }
  82. }
  83. // Takes an address of the form ('192.168.0.1', 8080), returns the port and
  84. // puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
  85. mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
  86. mp_obj_t *addr_items;
  87. mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
  88. netutils_parse_ipv4_addr(addr_items[0], out_ip, endian);
  89. return mp_obj_get_int(addr_items[1]);
  90. }