HAL_TCP_rtthread.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * Copyright (c) 2006-2018 RT-Thread Development Team. All rights reserved.
  3. * License-Identifier: Apache-2.0
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  6. * not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. * Again edit by rt-thread group
  18. * Change Logs:
  19. * Date Author Notes
  20. * 2019-07-21 MurphyZhao first edit
  21. */
  22. #include <rtthread.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <sys/time.h>
  27. #include <sys/socket.h>
  28. #include <sys/select.h>
  29. #include <sys/errno.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <netinet/tcp.h>
  33. #include <netdb.h>
  34. #define DBG_TAG "ali.tcp"
  35. #define DBG_LVL DBG_INFO
  36. #include <rtdbg.h>
  37. extern void HAL_Printf(const char *fmt, ...);
  38. extern uint64_t HAL_UptimeMs(void);
  39. static uint64_t _rtthread_time_left(uint64_t t_end, uint64_t t_now)
  40. {
  41. uint64_t t_left;
  42. if (t_end > t_now) {
  43. t_left = t_end - t_now;
  44. } else {
  45. t_left = 0;
  46. }
  47. return t_left;
  48. }
  49. uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
  50. {
  51. struct addrinfo hints;
  52. struct addrinfo *addrInfoList = NULL;
  53. struct addrinfo *cur = NULL;
  54. int fd = 0;
  55. int rc = 0;
  56. char service[6];
  57. memset(&hints, 0, sizeof(hints));
  58. LOG_D("establish tcp connection with server(host=%s port=%d)", host, port);
  59. hints.ai_family = AF_INET; /* only IPv4 */
  60. hints.ai_socktype = SOCK_STREAM;
  61. hints.ai_protocol = IPPROTO_TCP;
  62. sprintf(service, "%u", port);
  63. if ((rc = getaddrinfo(host, service, &hints, &addrInfoList)) != 0) {
  64. LOG_E("getaddrinfo error");
  65. return 0;
  66. }
  67. for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) {
  68. if (cur->ai_family != AF_INET) {
  69. LOG_E("socket type error");
  70. rc = 0;
  71. continue;
  72. }
  73. fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
  74. if (fd < 0) {
  75. LOG_E("create socket error");
  76. rc = 0;
  77. continue;
  78. }
  79. if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
  80. rc = fd;
  81. break;
  82. }
  83. close(fd);
  84. LOG_E("connect error");
  85. rc = 0;
  86. }
  87. if (0 == rc) {
  88. LOG_E("fail to establish tcp");
  89. } else {
  90. LOG_D("success to establish tcp, fd=%d", rc);
  91. }
  92. freeaddrinfo(addrInfoList);
  93. return (uintptr_t)rc;
  94. }
  95. int32_t HAL_TCP_Destroy(uintptr_t fd)
  96. {
  97. int rc;
  98. rc = closesocket((int) fd);
  99. if (0 != rc) {
  100. LOG_E("closesocket error");
  101. return -1;
  102. }
  103. return 0;
  104. }
  105. int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
  106. {
  107. int ret;
  108. uint32_t len_sent;
  109. uint64_t t_end, t_left;
  110. fd_set sets;
  111. t_end = HAL_UptimeMs() + timeout_ms;
  112. len_sent = 0;
  113. ret = 1; /* send one time if timeout_ms is value 0 */
  114. do {
  115. t_left = _rtthread_time_left(t_end, HAL_UptimeMs());
  116. if (0 != t_left) {
  117. struct timeval timeout;
  118. FD_ZERO(&sets);
  119. FD_SET(fd, &sets);
  120. timeout.tv_sec = t_left / 1000;
  121. timeout.tv_usec = (t_left % 1000) * 1000;
  122. ret = select(fd + 1, NULL, &sets, NULL, &timeout);
  123. if (ret > 0) {
  124. if (0 == FD_ISSET(fd, &sets)) {
  125. LOG_E("Should NOT arrive");
  126. /* If timeout in next loop, it will not sent any data */
  127. ret = 0;
  128. continue;
  129. }
  130. } else if (0 == ret) {
  131. LOG_E("select-write timeout %d", timeout_ms);
  132. break;
  133. } else {
  134. if (EINTR == errno) {
  135. LOG_E("EINTR be caught");
  136. continue;
  137. }
  138. LOG_E("select-write fail");
  139. break;
  140. }
  141. }
  142. if (ret > 0) {
  143. ret = send(fd, buf + len_sent, len - len_sent, 0);
  144. if (ret > 0) {
  145. len_sent += ret;
  146. } else if (0 == ret) {
  147. LOG_E("No data be sent");
  148. } else {
  149. if (EINTR == errno) {
  150. LOG_E("EINTR be caught");
  151. continue;
  152. }
  153. LOG_E("send fail");
  154. break;
  155. }
  156. }
  157. } while ((len_sent < len) && (_rtthread_time_left(t_end, HAL_UptimeMs()) > 0));
  158. return len_sent;
  159. }
  160. int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
  161. {
  162. int ret, err_code;
  163. uint32_t len_recv;
  164. uint64_t t_end, t_left;
  165. fd_set sets;
  166. struct timeval timeout;
  167. t_end = HAL_UptimeMs() + timeout_ms;
  168. len_recv = 0;
  169. err_code = 0;
  170. do {
  171. t_left = _rtthread_time_left(t_end, HAL_UptimeMs());
  172. if (0 == t_left) {
  173. break;
  174. }
  175. FD_ZERO(&sets);
  176. FD_SET(fd, &sets);
  177. timeout.tv_sec = t_left / 1000;
  178. timeout.tv_usec = (t_left % 1000) * 1000;
  179. ret = select(fd + 1, &sets, NULL, NULL, &timeout);
  180. if (ret > 0) {
  181. ret = recv(fd, buf + len_recv, len - len_recv, 0);
  182. if (ret > 0) {
  183. len_recv += ret;
  184. } else if (0 == ret) {
  185. LOG_E("connection is closed");
  186. err_code = -1;
  187. break;
  188. } else {
  189. if (EINTR == errno) {
  190. LOG_E("EINTR be caught");
  191. continue;
  192. }
  193. LOG_E("recv fail");
  194. err_code = -2;
  195. break;
  196. }
  197. } else if (0 == ret) {
  198. break;
  199. } else {
  200. LOG_E("select-recv fail");
  201. err_code = -2;
  202. break;
  203. }
  204. } while ((len_recv < len));
  205. /* priority to return data bytes if any data be received from TCP connection. */
  206. /* It will get error code on next calling */
  207. return (0 != len_recv) ? len_recv : err_code;
  208. }