#include "sock.hpp"
#include <arpa/inet.h>
#include <fcntl.h>
int sock_listen(in_port_t port) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
LOG_ERRNO("socket(SOCK_STREAM)");
return -1;
}
int tmp = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) == -1) {
LOG_ERRNO("setsockopt(SO_REUSEADDR)");
close(fd);
return -1;
}
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(port);
if (bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
LOG_ERRNO("bind(%d)", port);
close(fd);
return -1;
}
if (listen(fd, 10) == -1) {
LOG_ERRNO("listen(%d)", port);
close(fd);
return -1;
}
LOG("listening...");
return fd;
}
int sock_accept(int fd, bool nonblock) {
sockaddr_in addr;
socklen_t alen = sizeof(addr);
int rv = accept4(fd, (sockaddr*)&addr, &alen, nonblock? SOCK_NONBLOCK: 0);
if (rv == -1) {
LOG_ERRNO("accept()");
} else {
LOG("accepted from %s:%d", inet_ntoa(addr.sin_addr), htons(addr.sin_port));
}
return rv;
}
int sock_connect(const sockaddr_in* addr, bool nonblock) {
LOG("connecting to %s:%d ...", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
int fd = socket(AF_INET, SOCK_STREAM|(nonblock? SOCK_NONBLOCK: 0), 0);
if (fd == -1) {
LOG_ERRNO("socket()");
return -1;
}
if (connect(fd, (struct sockaddr*)addr, sizeof(*addr)) == -1) {
if (errno != EINPROGRESS) {
LOG_ERRNO("connect()");
close(fd);
return -1;
}
}
return fd;
}
bool sock_nonblock(int fd, bool nonblock) {
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
LOG_ERRNO("fcntl(GETFL)");
return false;
}
flags = nonblock? (flags|O_NONBLOCK): (flags&~O_NONBLOCK);
if (fcntl(fd, F_SETFL, flags) == -1) {
LOG_ERRNO("fcntl(SETFL)");
return false;
}
return true;
}