network.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (C) 2019-2020 Alibaba Group Holding Limited
  3. */
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <sys/select.h>
  9. #include <sys/time.h>
  10. #include "aos/kernel.h"
  11. #include "network.h"
  12. static int net_read(network_t *n, unsigned char *buf, int count, int timeout_ms)
  13. {
  14. fd_set fds;
  15. int lfirst = 1;
  16. int rc, len = 0, fd;
  17. struct timeval tv;
  18. unsigned long long delta;
  19. struct timeval t1 = {0}, t2 = {0};
  20. if (!(n && buf && count)) {
  21. return -1;
  22. }
  23. fd = n->fd;
  24. tv.tv_sec = timeout_ms / 1000;
  25. tv.tv_usec = (timeout_ms % 1000) * 1000;
  26. gettimeofday(&t1, NULL);
  27. while (len < count) {
  28. FD_ZERO(&fds);
  29. FD_SET(fd, &fds);
  30. /* FIXME: patch for select. */
  31. if (lfirst) {
  32. lfirst = 0;
  33. } else {
  34. gettimeofday(&t2, NULL);
  35. delta = (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
  36. if (delta >= timeout_ms)
  37. break;
  38. }
  39. rc = select(fd + 1, &fds, NULL, NULL, &tv);
  40. if (rc < 0) {
  41. if ((errno == EINTR) || (errno == EAGAIN)) {
  42. aos_msleep(20);
  43. continue;
  44. }
  45. return -1;
  46. } else if (rc == 0) {
  47. /* time out */
  48. break;
  49. }
  50. if (!FD_ISSET(fd, &fds)) {
  51. aos_msleep(20);
  52. continue;
  53. }
  54. rc = recv(fd, buf + len, count - len, 0);
  55. if (rc < 0) {
  56. if ((errno == EINTR) || (errno == EAGAIN)) {
  57. aos_msleep(20);
  58. continue;
  59. }
  60. return -1;
  61. } else if (rc == 0) {
  62. /* the sockfd may be closed */
  63. break;
  64. }
  65. len += rc;
  66. }
  67. return len;
  68. }
  69. /**
  70. * @brief write n bytes from a sockfd with timeout
  71. * @param [in] fd
  72. * @param [in] buf
  73. * @param [in] count
  74. * @param [in] timeout_ms
  75. * @return -1 on err
  76. */
  77. static int net_write(network_t *n, unsigned char *buf, int count, int timeout_ms)
  78. {
  79. fd_set fds;
  80. int lfirst = 1;
  81. int rc, len = 0, fd;
  82. struct timeval tv;
  83. unsigned long long delta;
  84. struct timeval t1 = {0}, t2 = {0};
  85. if (!(n && buf && count)) {
  86. return -1;
  87. }
  88. fd = n->fd;
  89. tv.tv_sec = timeout_ms / 1000;
  90. tv.tv_usec = (timeout_ms % 1000) * 1000;
  91. gettimeofday(&t1, NULL);
  92. while (len < count) {
  93. FD_ZERO(&fds);
  94. FD_SET(fd, &fds);
  95. /* FIXME: patch for select. */
  96. if (lfirst) {
  97. lfirst = 0;
  98. } else {
  99. gettimeofday(&t2, NULL);
  100. delta = (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
  101. if (delta >= timeout_ms)
  102. break;
  103. }
  104. rc = select(fd + 1, NULL, &fds, NULL, &tv);
  105. if (rc < 0) {
  106. if ((errno == EINTR) || (errno == EAGAIN)) {
  107. aos_msleep(20);
  108. continue;
  109. }
  110. return -1;
  111. } else if (rc == 0) {
  112. /* time out */
  113. break;
  114. }
  115. if (!FD_ISSET(fd, &fds)) {
  116. aos_msleep(20);
  117. continue;
  118. }
  119. rc = sendto(fd, buf + len, count - len, 0,
  120. (struct sockaddr *)&(n->address),
  121. sizeof(n->address));
  122. if (rc < 0) {
  123. if ((errno == EINTR) || (errno == EAGAIN)) {
  124. aos_msleep(20);
  125. continue;
  126. }
  127. return -1;
  128. } else if (rc == 0) {
  129. /* the sockfd may be closed */
  130. break;
  131. }
  132. len += rc;
  133. }
  134. return len;
  135. }
  136. static int net_connect(network_t *n, char *addr, int port, int net_type)
  137. {
  138. int rc = -1;
  139. sa_family_t family = AF_INET;
  140. struct addrinfo *result = NULL;
  141. struct addrinfo hints = {0, AF_UNSPEC, net_type, 0, 0, NULL, NULL, NULL};
  142. if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0) {
  143. struct addrinfo *res = result;
  144. /* prefer ip4 addresses */
  145. while (res) {
  146. if (res->ai_family == AF_INET) {
  147. result = res;
  148. break;
  149. }
  150. res = res->ai_next;
  151. }
  152. if (result->ai_family == AF_INET) {
  153. n->address.sin_port = htons(port);
  154. n->address.sin_family = family = AF_INET;
  155. n->address.sin_addr = ((struct sockaddr_in *)(result->ai_addr))->sin_addr;
  156. } else {
  157. rc = -1;
  158. }
  159. freeaddrinfo(result);
  160. }
  161. if (rc == 0) {
  162. n->fd = socket(family, net_type, 0);
  163. if (n->fd != -1) {
  164. rc = connect(n->fd, (struct sockaddr *)&n->address, sizeof(n->address));
  165. }
  166. if (rc < 0) {
  167. close(n->fd);
  168. n->fd = 0;
  169. }
  170. }
  171. return rc;
  172. }
  173. static void net_disconnect(network_t *n)
  174. {
  175. close(n->fd);
  176. n->fd = 0;
  177. }
  178. void network_init(network_t *n)
  179. {
  180. n->fd = 0;
  181. n->net_read = net_read;
  182. n->net_write = net_write;
  183. n->net_connect = net_connect;
  184. n->net_disconncet = net_disconnect;
  185. }