send_recv.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <arpa/inet.h>
  6. #include <assert.h>
  7. #include <netinet/in.h>
  8. #include <stdarg.h>
  9. #include <stdbool.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdint.h>
  13. #include <string.h>
  14. #include <sys/socket.h>
  15. #include <unistd.h>
  16. #ifdef __wasi__
  17. #include <wasi_socket_ext.h>
  18. #include "pthread.h"
  19. #else
  20. #include <pthread.h>
  21. #endif
  22. static pthread_mutex_t lock = { 0 };
  23. static pthread_cond_t cond = { 0 };
  24. static bool server_create_failed = false;
  25. static bool server_is_ready = false;
  26. #ifdef __wasi__
  27. __attribute__((import_name("log"))) extern void
  28. host_log(uint64_t message, uint32_t length);
  29. #endif
  30. static void
  31. local_printf(const char *formatter, ...)
  32. {
  33. char buffer[128] = { 0 };
  34. va_list args;
  35. va_start(args, formatter);
  36. vsnprintf(buffer, 128, formatter, args);
  37. va_end(args);
  38. #ifdef __wasi__
  39. host_log((uint64_t)(void *)buffer, strlen(buffer));
  40. #endif
  41. printf("--> %s", buffer);
  42. }
  43. void *
  44. run_as_server(void *arg)
  45. {
  46. (void)arg;
  47. int sock = -1, on = 1;
  48. struct sockaddr_in addr = { 0 };
  49. int addrlen = 0;
  50. int new_sock = -1;
  51. char *buf[] = {
  52. "The stars shine down", "It brings us light", "Light comes down",
  53. "To make us paths", "It watches us", "And mourns for us",
  54. };
  55. struct iovec iov[] = {
  56. { .iov_base = buf[0], .iov_len = strlen(buf[0]) + 1 },
  57. { .iov_base = buf[1], .iov_len = strlen(buf[1]) + 1 },
  58. { .iov_base = buf[2], .iov_len = strlen(buf[2]) + 1 },
  59. { .iov_base = buf[3], .iov_len = strlen(buf[3]) + 1 },
  60. { .iov_base = buf[4], .iov_len = strlen(buf[4]) + 1 },
  61. { .iov_base = buf[5], .iov_len = strlen(buf[5]) + 1 },
  62. };
  63. struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 6 };
  64. ssize_t send_len = 0;
  65. pthread_mutex_lock(&lock);
  66. sock = socket(AF_INET, SOCK_STREAM, 0);
  67. if (sock < 0) {
  68. server_create_failed = true;
  69. pthread_cond_signal(&cond);
  70. pthread_mutex_unlock(&lock);
  71. perror("Create a socket failed");
  72. return NULL;
  73. }
  74. #ifndef __wasi__
  75. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) {
  76. server_create_failed = true;
  77. pthread_cond_signal(&cond);
  78. pthread_mutex_unlock(&lock);
  79. perror("Setsockopt failed");
  80. goto fail1;
  81. }
  82. #endif
  83. /* 0.0.0.0:1234 */
  84. addr.sin_family = AF_INET;
  85. addr.sin_port = htons(1234);
  86. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  87. addrlen = sizeof(addr);
  88. if (bind(sock, (struct sockaddr *)&addr, addrlen) < 0) {
  89. server_create_failed = true;
  90. pthread_cond_signal(&cond);
  91. pthread_mutex_unlock(&lock);
  92. perror("Bind failed");
  93. goto fail1;
  94. }
  95. if (listen(sock, 0) < 0) {
  96. server_create_failed = true;
  97. pthread_cond_signal(&cond);
  98. pthread_mutex_unlock(&lock);
  99. perror("Listen failed");
  100. goto fail1;
  101. }
  102. server_is_ready = true;
  103. pthread_cond_signal(&cond);
  104. pthread_mutex_unlock(&lock);
  105. local_printf("Server is online ... \n");
  106. new_sock = accept(sock, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
  107. if (new_sock < 0) {
  108. perror("Accept failed");
  109. goto fail1;
  110. }
  111. local_printf("Start sending. \n");
  112. send_len = sendmsg(new_sock, &msg, 0);
  113. if (send_len < 0) {
  114. perror("Sendmsg failed");
  115. goto fail2;
  116. }
  117. local_printf("Send %ld bytes successfully!\n", send_len);
  118. fail2:
  119. close(new_sock);
  120. fail1:
  121. shutdown(sock, SHUT_RDWR);
  122. close(sock);
  123. return NULL;
  124. }
  125. void *
  126. run_as_client(void *arg)
  127. {
  128. (void)arg;
  129. int sock = -1;
  130. struct sockaddr_in addr = { 0 };
  131. /* buf of server is 106 bytes */
  132. char buf[110] = { 0 };
  133. struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
  134. struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
  135. ssize_t recv_len = 0;
  136. pthread_mutex_lock(&lock);
  137. while (!server_create_failed && !server_is_ready) {
  138. pthread_cond_wait(&cond, &lock);
  139. }
  140. pthread_mutex_unlock(&lock);
  141. if (server_create_failed) {
  142. return NULL;
  143. }
  144. local_printf("Client is running...\n");
  145. sock = socket(AF_INET, SOCK_STREAM, 0);
  146. if (sock < 0) {
  147. perror("Create a socket failed");
  148. return NULL;
  149. }
  150. /* 127.0.0.1:1234 */
  151. addr.sin_family = AF_INET;
  152. addr.sin_port = htons(1234);
  153. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  154. if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  155. perror("Connect failed");
  156. goto fail;
  157. }
  158. local_printf("Start receiving. \n");
  159. recv_len = recvmsg(sock, &msg, 0);
  160. if (recv_len < 0) {
  161. perror("Recvmsg failed");
  162. goto fail;
  163. }
  164. local_printf("Receive %ld bytes successfully!\n", recv_len);
  165. assert(recv_len == 106);
  166. local_printf("Data:\n");
  167. char *s = msg.msg_iov->iov_base;
  168. while (strlen(s) > 0) {
  169. local_printf(" %s\n", s);
  170. s += strlen(s) + 1;
  171. }
  172. fail:
  173. shutdown(sock, SHUT_RDWR);
  174. close(sock);
  175. return NULL;
  176. }
  177. int
  178. main(int argc, char *argv[])
  179. {
  180. (void)argc;
  181. (void)argv;
  182. pthread_t cs[2] = { 0 };
  183. uint8_t i = 0;
  184. int ret = EXIT_SUCCESS;
  185. if (pthread_mutex_init(&lock, NULL)) {
  186. perror("Initialize mutex failed");
  187. ret = EXIT_FAILURE;
  188. goto RETURN;
  189. }
  190. if (pthread_cond_init(&cond, NULL)) {
  191. perror("Initialize condition failed");
  192. ret = EXIT_FAILURE;
  193. goto DESTROY_MUTEX;
  194. }
  195. if (pthread_create(&cs[0], NULL, run_as_server, NULL)) {
  196. perror("Create a server thread failed");
  197. ret = EXIT_FAILURE;
  198. goto DESTROY_COND;
  199. }
  200. if (pthread_create(&cs[1], NULL, run_as_client, NULL)) {
  201. perror("Create a client thread failed");
  202. ret = EXIT_FAILURE;
  203. goto DESTROY_COND;
  204. }
  205. for (i = 0; i < 2; i++) {
  206. pthread_join(cs[i], NULL);
  207. }
  208. DESTROY_COND:
  209. pthread_cond_destroy(&cond);
  210. DESTROY_MUTEX:
  211. pthread_mutex_destroy(&lock);
  212. RETURN:
  213. return ret;
  214. }