#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include "./SocketUtils.h"
void PrintOut(int fd, struct sockaddr *addr, size_t) {
std::cout << "Socket [" << fd << "] is bound to:" << std::endl;
if (addr->sa_family == AF_INET) {
char astring[INET_ADDRSTRLEN];
struct sockaddr_in *in4 = reinterpret_cast<struct sockaddr_in *>(addr);
inet_ntop(AF_INET, &(in4->sin_addr), astring, INET_ADDRSTRLEN);
std::cout << " IPv4 address " << astring;
std::cout << " and port " << htons(in4->sin_port) << std::endl;
} else if (addr->sa_family == AF_INET6) {
char astring[INET6_ADDRSTRLEN];
struct sockaddr_in6 *in6 = reinterpret_cast<struct sockaddr_in6 *>(addr);
inet_ntop(AF_INET6, &(in6->sin6_addr), astring, INET6_ADDRSTRLEN);
std::cout << " IPv6 address " << astring;
std::cout << " and port " << htons(in6->sin6_port) << std::endl;
} else {
std::cout << " ???? address and port ????" << std::endl;
}
}
void PrintReverseDNS(struct sockaddr *addr, size_t addrlen) {
char hostname[1024];
if (getnameinfo(addr, addrlen, hostname, 1024, NULL, 0, 0) != 0) {
snprintf(hostname, sizeof(hostname), "[reverse DNS failed]");
}
std::cout << " DNS name: " << hostname << std::endl;
}
void PrintServerSide(int client_fd, int sock_family) {
char hname[1024];
hname[0] = '\0';
std::cout << "Server side interface is ";
if (sock_family == AF_INET) {
struct sockaddr_in srvr;
socklen_t srvrlen = sizeof(srvr);
char addrbuf[INET_ADDRSTRLEN];
getsockname(client_fd, (struct sockaddr *) &srvr, &srvrlen);
inet_ntop(AF_INET, &srvr.sin_addr, addrbuf, INET_ADDRSTRLEN);
std::cout << addrbuf;
getnameinfo((const struct sockaddr *) &srvr,
srvrlen, hname, 1024, NULL, 0, 0);
std::cout << " [" << hname << "]" << std::endl;
} else {
struct sockaddr_in6 srvr;
socklen_t srvrlen = sizeof(srvr);
char addrbuf[INET6_ADDRSTRLEN];
getsockname(client_fd, (struct sockaddr *) &srvr, &srvrlen);
inet_ntop(AF_INET6, &srvr.sin6_addr, addrbuf, INET6_ADDRSTRLEN);
std::cout << addrbuf;
getnameinfo((const struct sockaddr *) &srvr,
srvrlen, hname, 1024, NULL, 0, 0);
std::cout << " [" << hname << "]" << std::endl;
}
}
int Listen(char *portnum, int *sock_family) {
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
struct addrinfo *result;
int res = getaddrinfo(NULL, portnum, &hints, &result);
if (res != 0) {
std::cerr << "getaddrinfo() failed: ";
std::cerr << gai_strerror(res) << std::endl;
return -1;
}
int listen_fd = -1;
for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) {
listen_fd = socket(rp->ai_family,
rp->ai_socktype,
rp->ai_protocol);
if (listen_fd == -1) {
std::cerr << "socket() failed: " << strerror(errno) << std::endl;
listen_fd = -1;
continue;
}
int optval = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
&optval, sizeof(optval));
if (bind(listen_fd, rp->ai_addr, rp->ai_addrlen) == 0) {
PrintOut(listen_fd, rp->ai_addr, rp->ai_addrlen);
*sock_family = rp->ai_family;
break;
}
close(listen_fd);
listen_fd = -1;
}
freeaddrinfo(result);
if (listen_fd <= 0)
return listen_fd;
if (listen(listen_fd, SOMAXCONN) != 0) {
std::cerr << "Failed to mark socket as listening: ";
std::cerr << strerror(errno) << std::endl;
close(listen_fd);
return -1;
}
return listen_fd;
}
unsigned int WrappedWrite(int fd, unsigned char *buf, unsigned int writelen) {
unsigned int written_so_far = 0;
while (written_so_far < writelen) {
int res = write(fd, buf + written_so_far, writelen - written_so_far);
if (res == -1) {
if ((errno == EAGAIN) || (errno == EINTR))
continue;
break;
}
if (res == 0)
break;
written_so_far += res;
}
return written_so_far;
}