Moontalk server and client (provided by many parties)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
2.6KB

  1. /* blackhole.c - eats incoming messages, does nothing, just for testing
  2. * @BAKE cc -O2 -std=gnu89 -Wall -Wextra -Wpedantic $@ -o $*
  3. * Basically ripped from <https://beej.us/guide/bgnet/html//index.html#what-is-a-socket>
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <errno.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <netdb.h>
  14. #include <arpa/inet.h>
  15. #include <sys/wait.h>
  16. #include <signal.h>
  17. #define PORT "91991"
  18. #define BACKLOG 1
  19. void sigchld_handler(int s) {
  20. int saved_errno = errno;
  21. (void)s;
  22. while(waitpid(-1, NULL, WNOHANG) > 0);
  23. errno = saved_errno;
  24. }
  25. void *get_in_addr(struct sockaddr *sa) {
  26. if (sa->sa_family == AF_INET) {
  27. return &(((struct sockaddr_in*)sa)->sin_addr);
  28. }
  29. return &(((struct sockaddr_in6*)sa)->sin6_addr);
  30. }
  31. int main (void) {
  32. int sockfd, connfd, rv, yes = 1;
  33. struct addrinfo hints, *servinfo, *p;
  34. struct sockaddr_storage their_addr;
  35. char s[INET6_ADDRSTRLEN];
  36. socklen_t sin_size;
  37. struct sigaction sa;
  38. memset(&hints, 0, sizeof hints);
  39. hints.ai_family = AF_UNSPEC;
  40. hints.ai_socktype = SOCK_STREAM;
  41. hints.ai_flags = AI_PASSIVE;
  42. if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
  43. fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
  44. return 1;
  45. }
  46. for(p = servinfo; p != NULL; p = p->ai_next) {
  47. if ((sockfd = socket(p->ai_family, p->ai_socktype,
  48. p->ai_protocol)) == -1) {
  49. perror("server: socket");
  50. continue;
  51. }
  52. if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
  53. sizeof(int)) == -1) {
  54. perror("setsockopt");
  55. exit(1);
  56. }
  57. if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
  58. close(sockfd);
  59. perror("server: bind");
  60. continue;
  61. }
  62. break;
  63. }
  64. freeaddrinfo(servinfo);
  65. if (p == NULL) {
  66. fprintf(stderr, "server: failed to bind\n");
  67. exit(1);
  68. }
  69. if (listen(sockfd, BACKLOG) == -1) {
  70. perror("listen");
  71. exit(1);
  72. }
  73. sa.sa_handler = sigchld_handler;
  74. sigemptyset(&sa.sa_mask);
  75. sa.sa_flags = SA_RESTART;
  76. if (sigaction(SIGCHLD, &sa, NULL) == -1) {
  77. perror("sigaction");
  78. exit(1);
  79. }
  80. printf("server: waiting for connections...\n");
  81. while (1) {
  82. sin_size = sizeof their_addr;
  83. connfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
  84. if (connfd == -1) {
  85. perror("accept");
  86. continue;
  87. }
  88. inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
  89. printf("server: got connection from %s\n", s);
  90. if (!fork()) {
  91. close(sockfd);
  92. while (1) { sleep(5); }
  93. close(connfd);
  94. exit(0);
  95. }
  96. close(connfd);
  97. }
  98. close(sockfd);
  99. sockfd = -1;
  100. return 0;
  101. }