#include "TcpSocket.hpp" #include #include #include #include #include #include #include #include #include #include namespace TcpSocket { void setTimeout(int seconds, int sock) { struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = 0; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); } ssize_t sendt(int sock, const void *bytes, size_t byteslength) { return send(sock, bytes, byteslength, 0); } ssize_t recvt(int sock, void *bytes, size_t byteslength) { return recv(sock, bytes, byteslength, 0); } void closet(int sock) { shutdown(sock, SHUT_RDWR); close(sock); } std::string remoteAddress(sockaddr_in &address) { char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(address.sin_addr), ip, INET_ADDRSTRLEN); return std::string(ip); } int remotePort(sockaddr_in &address) { return ntohs(address.sin_port); } int connectt(const char *host, uint16_t port) { struct addrinfo hints, *res, *it; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; // Get address info from DNS int status = getaddrinfo(host, NULL, &hints, &res); if (status != 0) { // onError(errno, "Invalid address." + std::string(gai_strerror(status))); return -1; } sockaddr_in address; for (it = res; it != NULL; it = it->ai_next) { if (it->ai_family == AF_INET) { // IPv4 memcpy((void *)(&address), (void *)it->ai_addr, sizeof(sockaddr_in)); break; // for now, just get the first ip (ipv4). } } freeaddrinfo(res); int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { // onError(errno, "Socket creating error."); return -2; } address.sin_family = AF_INET; address.sin_port = htons(port); // setTimeout(5, sock); // Try to connect. status = connect(sock, (const sockaddr *)&address, sizeof(sockaddr_in)); if (status == -1) { // onError(errno, "Connection failed to the host."); close(sock); return -3; } return sock; } int listent(const char *host, uint16_t port, OnNewConnectionCallBack callback) { sockaddr_in address; int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { // onError(errno, "Socket creating error."); return -1; } int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(int)); int status = inet_pton(AF_INET, host, &address.sin_addr); switch (status) { case -1: close(sock); // onError(errno, "Invalid address. Address type not supported."); return -2; case 0: close(sock); // onError(errno, "AF_INET is not supported. Please send message to developer."); return -3; default: break; } address.sin_family = AF_INET; address.sin_port = htons(port); if (bind(sock, (const sockaddr *)&address, sizeof(address)) == -1) { // onError(errno, "Cannot bind the socket."); close(sock); return -4; } if (listen(sock, 20) == -1) { // onError(errno, "Error: Server can't listen the socket."); close(sock); return -5; } sockaddr_in newSocketInfo; socklen_t newSocketInfoLength = sizeof(newSocketInfo); int newSocketFileDescriptor = -1; while (true) { newSocketFileDescriptor = accept(sock, (sockaddr *)&newSocketInfo, &newSocketInfoLength); if (newSocketFileDescriptor == -1) { if (errno == EBADF || errno == EINVAL) return -6; return -7; } std::thread t(callback, newSocketFileDescriptor, newSocketInfo); t.detach(); } return 0; } }