HAL_TCP_rtthread.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 <unistd.h>
  30. #include <fcntl.h>
  31. #include <netinet/tcp.h>
  32. #include <netdb.h>
  33. #define DBG_TAG "ali.tcp"
  34. #define DBG_LVL DBG_INFO
  35. #include <rtdbg.h>
  36. extern void HAL_Printf(const char *fmt, ...);
  37. extern uint64_t HAL_UptimeMs(void);
  38. static uint64_t _rtthread_time_left(uint64_t t_end, uint64_t t_now)
  39. {
  40. uint64_t t_left;
  41. if (t_end > t_now) {
  42. t_left = t_end - t_now;
  43. } else {
  44. t_left = 0;
  45. }
  46. return t_left;
  47. }
  48. uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
  49. {
  50. struct addrinfo hints;
  51. struct addrinfo *addrInfoList = NULL;
  52. struct addrinfo *cur = NULL;
  53. int fd = 0;
  54. int rc = 0;
  55. char service[6];
  56. memset(&hints, 0, sizeof(hints));
  57. LOG_D("establish tcp connection with server(host=%s port=%d)", host, port);
  58. hints.ai_family = AF_INET; /* only IPv4 */
  59. hints.ai_socktype = SOCK_STREAM;
  60. hints.ai_protocol = IPPROTO_TCP;
  61. sprintf(service, "%u", port);
  62. if ((rc = getaddrinfo(host, service, &hints, &addrInfoList)) != 0) {
  63. LOG_E("getaddrinfo error");
  64. return 0;
  65. }
  66. for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) {
  67. if (cur->ai_family != AF_INET) {
  68. LOG_E("socket type error");
  69. rc = 0;
  70. continue;
  71. }
  72. fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
  73. if (fd < 0) {
  74. LOG_E("create socket error");
  75. rc = 0;
  76. continue;
  77. }
  78. if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
  79. rc = fd;
  80. break;
  81. }
  82. close(fd);
  83. LOG_E("connect error");
  84. rc = 0;
  85. }
  86. if (0 == rc) {
  87. LOG_E("fail to establish tcp");
  88. } else {
  89. LOG_D("success to establish tcp, fd=%d", rc);
  90. }
  91. freeaddrinfo(addrInfoList);
  92. return (uintptr_t)rc;
  93. }
  94. int32_t HAL_TCP_Destroy(uintptr_t fd)
  95. {
  96. int rc;
  97. rc = close((int) fd);
  98. if (0 != rc) {
  99. LOG_E("closesocket error");
  100. return -1;
  101. }
  102. return 0;
  103. }
  104. int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
  105. {
  106. int ret;
  107. uint32_t len_sent;
  108. uint64_t t_end, t_left;
  109. fd_set sets;
  110. t_end = HAL_UptimeMs() + timeout_ms;
  111. len_sent = 0;
  112. ret = 1; /* send one time if timeout_ms is value 0 */
  113. do {
  114. t_left = _rtthread_time_left(t_end, HAL_UptimeMs());
  115. if (0 != t_left) {
  116. struct timeval timeout;
  117. FD_ZERO(&sets);
  118. FD_SET(fd, &sets);
  119. timeout.tv_sec = t_left / 1000;
  120. timeout.tv_usec = (t_left % 1000) * 1000;
  121. ret = select(fd + 1, NULL, &sets, NULL, &timeout);
  122. if (ret > 0) {
  123. if (0 == FD_ISSET(fd, &sets)) {
  124. LOG_E("Should NOT arrive");
  125. /* If timeout in next loop, it will not sent any data */
  126. ret = 0;
  127. continue;
  128. }
  129. } else if (0 == ret) {
  130. LOG_E("select-write timeout %d", timeout_ms);
  131. break;
  132. } else {
  133. if (EINTR == errno) {
  134. LOG_E("EINTR be caught");
  135. continue;
  136. }
  137. LOG_E("select-write fail");
  138. break;
  139. }
  140. }
  141. if (ret > 0) {
  142. ret = send(fd, buf + len_sent, len - len_sent, 0);
  143. if (ret > 0) {
  144. len_sent += ret;
  145. } else if (0 == ret) {
  146. LOG_E("No data be sent");
  147. } else {
  148. if (EINTR == errno) {
  149. LOG_E("EINTR be caught");
  150. continue;
  151. }
  152. LOG_E("send fail");
  153. break;
  154. }
  155. }
  156. } while ((len_sent < len) && (_rtthread_time_left(t_end, HAL_UptimeMs()) > 0));
  157. return len_sent;
  158. }
  159. int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
  160. {
  161. int ret, err_code;
  162. uint32_t len_recv;
  163. uint64_t t_end, t_left;
  164. fd_set sets;
  165. struct timeval timeout;
  166. t_end = HAL_UptimeMs() + timeout_ms;
  167. len_recv = 0;
  168. err_code = 0;
  169. do {
  170. t_left = _rtthread_time_left(t_end, HAL_UptimeMs());
  171. if (0 == t_left) {
  172. break;
  173. }
  174. FD_ZERO(&sets);
  175. FD_SET(fd, &sets);
  176. timeout.tv_sec = t_left / 1000;
  177. timeout.tv_usec = (t_left % 1000) * 1000;
  178. ret = select(fd + 1, &sets, NULL, NULL, &timeout);
  179. if (ret > 0) {
  180. ret = recv(fd, buf + len_recv, len - len_recv, 0);
  181. if (ret > 0) {
  182. len_recv += ret;
  183. } else if (0 == ret) {
  184. LOG_E("connection is closed");
  185. err_code = -1;
  186. break;
  187. } else {
  188. if (EINTR == errno) {
  189. LOG_E("EINTR be caught");
  190. continue;
  191. }
  192. LOG_E("recv fail");
  193. err_code = -2;
  194. break;
  195. }
  196. } else if (0 == ret) {
  197. break;
  198. } else {
  199. LOG_E("select-recv fail");
  200. err_code = -2;
  201. break;
  202. }
  203. } while ((len_recv < len));
  204. /* priority to return data bytes if any data be received from TCP connection. */
  205. /* It will get error code on next calling */
  206. return (0 != len_recv) ? len_recv : err_code;
  207. }