#include #include #include #include #include "Practical.h" static const int MAX_PENDING = 5; int setup_tcp_server_socket(const char *service) { struct addrinfo addr_criteria = { 0 }; addr_criteria.ai_family = AF_UNSPEC; addr_criteria.ai_flags = AI_PASSIVE; addr_criteria.ai_socktype = SOCK_STREAM; addr_criteria.ai_protocol = proto_get_num("tcp"); struct addrinfo *serv_addr = nullptr; int ret = getaddrinfo(nullptr, service, &addr_criteria, &serv_addr); if (ret != 0) { DieWithUserMessage("getaddrinfo() failed", gai_strerror(ret)); } int serv_sock = -1; for (struct addrinfo *addr = serv_addr; addr != nullptr; addr = addr->ai_next) { serv_sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (serv_sock < 0) { continue; } if ( (bind(serv_sock, addr->ai_addr, addr->ai_addrlen) == 0) && (listen(serv_sock, MAX_PENDING) == 0) ) { struct sockaddr_storage local_addr; socklen_t addr_size = sizeof(local_addr); if (getsockname(serv_sock, (struct sockaddr *) &local_addr, &addr_size) < 0) { DieWithSystemMessage("getsockname() failed"); } fputs("Binding to: ", stdout); PrintSocketAddress((struct sockaddr *) &local_addr, stdout); fputc('\n', stdout); break; } else { close(serv_sock); serv_sock = -1; } } freeaddrinfo(serv_addr); return serv_sock; } int accept_tcp_connection(const int serv_sock) { struct sockaddr_storage client_addr; socklen_t client_addr_len = sizeof(client_addr); int client_sock = accept(serv_sock, (struct sockaddr *) &client_addr, &client_addr_len); if (client_sock < 0) { DieWithSystemMessage("accept() failed"); } fputs("Handling client ", stdout); PrintSocketAddress((struct sockaddr *) &client_addr, stdout); fputc('\n', stdout); return client_sock; } void HandleTCPClient(const int client_sock) { char buffer[BUFSIZE]; ssize_t num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0); if (num_bytes_rcvd < 0) { DieWithSystemMessage("recv() failed"); } while (num_bytes_rcvd > 0) { ssize_t num_bytes_sent = send(client_sock, buffer, num_bytes_rcvd, 0); if (num_bytes_sent < 0) { DieWithSystemMessage("send() failed"); } else if (num_bytes_sent != num_bytes_rcvd) { DieWithUserMessage("send()", "sent unexpected number of bytes"); } num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0); if (num_bytes_rcvd < 0) { DieWithSystemMessage("recv() failed"); } } close(client_sock); }