tcp_udp.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #ifdef __wasi__
  9. #include <wasi/api.h>
  10. #include <sys/socket.h>
  11. #include <wasi_socket_ext.h>
  12. #endif
  13. #include <arpa/inet.h>
  14. #include <pthread.h>
  15. #define SERVER_MSG "Message from server."
  16. #define PORT 8989
  17. pthread_mutex_t mut;
  18. pthread_cond_t cond;
  19. int server_init_complete = 0;
  20. char buffer[sizeof(SERVER_MSG) + 1];
  21. struct socket_info {
  22. union {
  23. struct sockaddr_in addr_ipv4;
  24. struct sockaddr_in6 addr_ipv6;
  25. } addr;
  26. int sock;
  27. };
  28. struct thread_args {
  29. int family;
  30. int protocol;
  31. };
  32. struct socket_info
  33. init_socket_addr(int family, int protocol)
  34. {
  35. int sock = socket(family, protocol, 0);
  36. assert(sock != -1);
  37. struct socket_info info;
  38. if (family == AF_INET) {
  39. struct sockaddr_in addr;
  40. memset(&addr, 0, sizeof(addr));
  41. addr.sin_family = AF_INET;
  42. addr.sin_port = htons(PORT);
  43. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  44. info.addr.addr_ipv4 = addr;
  45. }
  46. else if (family == AF_INET6) {
  47. struct sockaddr_in6 addr;
  48. memset(&addr, 0, sizeof(addr));
  49. addr.sin6_family = AF_INET6;
  50. addr.sin6_port = htons(PORT);
  51. addr.sin6_addr = in6addr_loopback;
  52. info.addr.addr_ipv6 = addr;
  53. }
  54. info.sock = sock;
  55. return info;
  56. }
  57. void
  58. assert_thread_args(struct thread_args *args)
  59. {
  60. assert(args->family == AF_INET || args->family == AF_INET6);
  61. assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
  62. }
  63. void *
  64. server(void *arg)
  65. {
  66. server_init_complete = 0;
  67. struct thread_args *args = (struct thread_args *)arg;
  68. assert_thread_args(args);
  69. struct socket_info init_server_sock =
  70. init_socket_addr(args->family, args->protocol);
  71. int server_sock = init_server_sock.sock;
  72. socklen_t addr_size;
  73. struct sockaddr_storage client_addr;
  74. strcpy(buffer, SERVER_MSG);
  75. struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
  76. int ret = bind(server_sock, server_addr,
  77. args->family == AF_INET ? sizeof(struct sockaddr_in)
  78. : sizeof(struct sockaddr_in6));
  79. assert(ret == 0);
  80. (args->protocol == SOCK_STREAM) && listen(server_sock, 1);
  81. pthread_mutex_lock(&mut);
  82. server_init_complete = 1;
  83. pthread_mutex_unlock(&mut);
  84. pthread_cond_signal(&cond);
  85. addr_size = sizeof(client_addr);
  86. if (args->protocol == SOCK_STREAM) {
  87. int client_sock =
  88. accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
  89. assert(client_sock >= 0);
  90. sendto(client_sock, buffer, strlen(buffer), 0,
  91. (struct sockaddr *)&client_addr, addr_size);
  92. assert(close(client_sock) == 0);
  93. }
  94. else {
  95. recvfrom(server_sock, buffer, sizeof(buffer), 0,
  96. (struct sockaddr *)&client_addr, &addr_size);
  97. sendto(server_sock, buffer, strlen(buffer), 0,
  98. (struct sockaddr *)&client_addr, addr_size);
  99. assert(close(server_sock) == 0);
  100. }
  101. return NULL;
  102. }
  103. void *
  104. client(void *arg)
  105. {
  106. struct thread_args *args = (struct thread_args *)arg;
  107. assert_thread_args(args);
  108. pthread_mutex_lock(&mut);
  109. while (server_init_complete == 0) {
  110. pthread_cond_wait(&cond, &mut);
  111. }
  112. struct socket_info init_client_sock =
  113. init_socket_addr(args->family, args->protocol);
  114. int sock = init_client_sock.sock;
  115. pthread_mutex_unlock(&mut);
  116. if (args->family == AF_INET) {
  117. struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
  118. if (args->protocol == SOCK_STREAM) {
  119. assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
  120. }
  121. else {
  122. assert(sendto(sock, buffer, strlen(buffer), 0,
  123. (struct sockaddr *)&addr, sizeof(addr))
  124. != -1);
  125. }
  126. }
  127. else {
  128. struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
  129. if (args->protocol == SOCK_STREAM) {
  130. assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
  131. }
  132. else {
  133. assert(sendto(sock, buffer, strlen(buffer), 0,
  134. (struct sockaddr *)&addr, sizeof(addr))
  135. != -1);
  136. }
  137. }
  138. recv(sock, buffer, sizeof(buffer), 0);
  139. assert(strcmp(buffer, SERVER_MSG) == 0);
  140. assert(close(sock) == 0);
  141. return NULL;
  142. }
  143. void
  144. test_protocol(int family, int protocol)
  145. {
  146. pthread_t server_thread, client_thread;
  147. assert(pthread_cond_init(&cond, NULL) == 0);
  148. assert(pthread_mutex_init(&mut, NULL) == 0);
  149. struct thread_args args = { family, protocol };
  150. assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
  151. assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
  152. assert(pthread_join(server_thread, NULL) == 0);
  153. assert(pthread_join(client_thread, NULL) == 0);
  154. assert(pthread_mutex_destroy(&mut) == 0);
  155. assert(pthread_cond_destroy(&cond) == 0);
  156. }
  157. int
  158. main(int argc, char **argv)
  159. {
  160. /* test tcp with ipv4 and ipv6 */
  161. test_protocol(AF_INET, SOCK_STREAM);
  162. test_protocol(AF_INET6, SOCK_STREAM);
  163. /* test udp with ipv4 and ipv6 */
  164. test_protocol(AF_INET, SOCK_DGRAM);
  165. test_protocol(AF_INET6, SOCK_DGRAM);
  166. return 0;
  167. }