tcp_udp.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. #include <errno.h>
  9. #include <time.h>
  10. #ifdef __wasi__
  11. #include <wasi/api.h>
  12. #include <sys/socket.h>
  13. #include <wasi_socket_ext.h>
  14. #endif
  15. #include <arpa/inet.h>
  16. #include <pthread.h>
  17. #include <stdio.h>
  18. #define SERVER_MSG "Message from server."
  19. #define PORT 8989
  20. pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  21. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  22. int server_init_complete = 0;
  23. typedef struct {
  24. struct sockaddr_storage addr;
  25. socklen_t addr_len;
  26. int sock;
  27. int protocol;
  28. } socket_info_t;
  29. void
  30. wait_for_server(int wait_time_seconds)
  31. {
  32. int res = 0;
  33. struct timespec ts;
  34. clock_gettime(CLOCK_REALTIME, &ts);
  35. ts.tv_sec += wait_time_seconds;
  36. pthread_mutex_lock(&mut);
  37. while (server_init_complete == 0) {
  38. res = pthread_cond_timedwait(&cond, &mut, &ts);
  39. if (res == ETIMEDOUT)
  40. break;
  41. }
  42. pthread_mutex_unlock(&mut);
  43. assert(res == 0);
  44. }
  45. void
  46. notify_server_started()
  47. {
  48. pthread_mutex_lock(&mut);
  49. server_init_complete = 1;
  50. pthread_cond_signal(&cond);
  51. pthread_mutex_unlock(&mut);
  52. }
  53. socket_info_t
  54. init_socket_addr(int family, int protocol)
  55. {
  56. socket_info_t info;
  57. info.sock = socket(family, protocol, 0);
  58. assert(info.sock != -1);
  59. info.protocol = protocol;
  60. memset(&info.addr, 0, sizeof(info.addr));
  61. if (family == AF_INET) {
  62. struct sockaddr_in *addr = (struct sockaddr_in *)&info.addr;
  63. addr->sin_family = AF_INET;
  64. addr->sin_port = htons(PORT);
  65. addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  66. info.addr_len = sizeof(struct sockaddr_in);
  67. }
  68. else if (family == AF_INET6) {
  69. struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&info.addr;
  70. addr->sin6_family = AF_INET6;
  71. addr->sin6_port = htons(PORT);
  72. addr->sin6_addr = in6addr_loopback;
  73. info.addr_len = sizeof(struct sockaddr_in6);
  74. }
  75. return info;
  76. }
  77. void *
  78. server(void *arg)
  79. {
  80. char buffer[sizeof(SERVER_MSG) + 1] = { 0 };
  81. struct sockaddr_storage client_addr;
  82. socket_info_t *info = (socket_info_t *)arg;
  83. struct sockaddr *server_addr = (struct sockaddr *)&info->addr;
  84. int server_sock = info->sock;
  85. int optval = 1;
  86. assert(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
  87. sizeof(optval))
  88. == 0);
  89. assert(bind(server_sock, server_addr, info->addr_len) == 0);
  90. if (info->protocol == SOCK_STREAM)
  91. listen(server_sock, 1);
  92. notify_server_started();
  93. socklen_t addr_size = info->addr_len;
  94. if (info->protocol == SOCK_STREAM) {
  95. int client_sock =
  96. accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
  97. assert(client_sock >= 0);
  98. assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
  99. strcpy(buffer, SERVER_MSG);
  100. assert(send(client_sock, buffer, sizeof(buffer), 0) > 0);
  101. assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
  102. }
  103. else {
  104. assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
  105. (struct sockaddr *)&client_addr, &addr_size)
  106. > 0);
  107. strcpy(buffer, SERVER_MSG);
  108. assert(sendto(server_sock, buffer, strlen(buffer), 0,
  109. (struct sockaddr *)&client_addr, addr_size)
  110. > 0);
  111. assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
  112. (struct sockaddr *)&client_addr, &addr_size)
  113. > 0);
  114. }
  115. assert(close(server_sock) == 0);
  116. return NULL;
  117. }
  118. void *
  119. client(void *arg)
  120. {
  121. char buffer[sizeof(SERVER_MSG) + 1];
  122. socket_info_t *info = (socket_info_t *)arg;
  123. int sock = info->sock;
  124. struct sockaddr *addr = (struct sockaddr *)&info->addr;
  125. wait_for_server(1);
  126. if (info->protocol == SOCK_STREAM) {
  127. assert(connect(sock, addr, info->addr_len) != -1);
  128. }
  129. assert(sendto(sock, "open", strlen("open"), 0, addr, info->addr_len) > 0);
  130. assert(recv(sock, buffer, sizeof(buffer), 0) > 0);
  131. assert(strncmp(buffer, SERVER_MSG, strlen(SERVER_MSG)) == 0);
  132. assert(sendto(sock, "close", sizeof("close"), 0, addr, info->addr_len) > 0);
  133. assert(close(sock) == 0);
  134. return NULL;
  135. }
  136. void
  137. test_protocol(int family, int protocol)
  138. {
  139. pthread_t server_thread, client_thread;
  140. socket_info_t server_info = init_socket_addr(family, protocol);
  141. socket_info_t client_info = init_socket_addr(family, protocol);
  142. printf("Testing address family: %d protocol: %d\n", family, protocol);
  143. server_init_complete = 0;
  144. assert(pthread_create(&server_thread, NULL, server, (void *)&server_info)
  145. == 0);
  146. assert(pthread_create(&client_thread, NULL, client, (void *)&client_info)
  147. == 0);
  148. assert(pthread_join(server_thread, NULL) == 0);
  149. assert(pthread_join(client_thread, NULL) == 0);
  150. }
  151. int
  152. main(int argc, char **argv)
  153. {
  154. /* test tcp with ipv4 and ipv6 */
  155. test_protocol(AF_INET, SOCK_STREAM);
  156. test_protocol(AF_INET6, SOCK_STREAM);
  157. /* test udp with ipv4 and ipv6 */
  158. test_protocol(AF_INET, SOCK_DGRAM);
  159. test_protocol(AF_INET6, SOCK_DGRAM);
  160. return 0;
  161. }