#include "server.hpp" #include <definitions.hpp> #include <sys/socket.h> Server::Server() { setup(DEFAULT_PORT); } Server::Server(const int &port) { setup(port); } Server::~Server() { close(mastersocket_fd); } void Server::setup(int port) { mastersocket_fd = socket(AF_INET, SOCK_STREAM, 0); if (mastersocket_fd < 0) { perror("Error creating socket"); } FD_ZERO(&masterfds); FD_ZERO(&tmpfds); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(port); bzero(input_buffer, INPUT_BUFFER_SIZE); // no random data in input buffer } void Server::initializeSocket() { int opt_value = 1; int rc = setsockopt(mastersocket_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt_value, sizeof(int)); if (rc < 0) { perror("setsocketopt() failed"); stop(); } } void Server::bindSocket() { int rc = bind(mastersocket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (rc < 0) { perror("bind() failed"); } FD_SET(mastersocket_fd, &masterfds); maxfd = mastersocket_fd; } void Server::startListen() { int rc = listen(mastersocket_fd, 3); if (rc < 0) { perror("listen() failed"); } } void Server::stop() { close(mastersocket_fd); } void Server::handleNewConnection() { socklen_t addrLen = sizeof(client_addr); tempsocket_fd = accept(mastersocket_fd, (struct sockaddr *)&client_addr, &addrLen); if (tempsocket_fd < 0) { perror("accept() failed"); } else { FD_SET(tempsocket_fd, &masterfds); if (tempsocket_fd > maxfd) { maxfd = tempsocket_fd; } } newConnectionCallback(tempsocket_fd); } void Server::recvInputFromExisting(int fd) { int nbytesrecv = recv(fd, input_buffer, INPUT_BUFFER_SIZE, 0); if (nbytesrecv <= 0) { if (nbytesrecv == 0) { disconnectCallback((uint16_t)fd); close(fd); FD_CLR(fd, &masterfds); return; } else { perror("recv() failed"); } close(fd); FD_CLR(fd, &masterfds); return; } receiveCallback(fd, input_buffer); // clear input buffer bzero(&input_buffer, INPUT_BUFFER_SIZE); } void Server::run() { tmpfds = masterfds; int sel = select(maxfd + 1, &tmpfds, NULL, NULL, NULL); if (sel < 0) { perror("select() failed"); stop(); } // loop over the set of file descriptors and see if we can act for (int i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &tmpfds)) { // there is something to be done if (mastersocket_fd == i) { // we have a new connection handleNewConnection(); } else { // new data on existing connection recvInputFromExisting(i); } } } } void Server::init() { initializeSocket(); bindSocket(); startListen(); } void Server::onInput(receiveCallbackType cb) { receiveCallback = cb; } void Server::onConnect(newConnectionCallbackType cb) { newConnectionCallback = cb; } void Server::onDisconnect(disconnectCallbackType cb) { disconnectCallback = cb; } uint16_t Server::sendMessage(int source_fd, char *messageBuffer) { return send(source_fd, messageBuffer, strlen(messageBuffer), 0); } uint16_t Server::sendMessage(int source_fd, const char *messageBuffer) { return send(source_fd, messageBuffer, strlen(messageBuffer), 0); }