From cd2decce51c32b8c0531a87ea849e9f8e80db0d3 Mon Sep 17 00:00:00 2001 From: Joursoir Date: Mon, 23 Nov 2020 20:07:36 +0300 Subject: server: add first (work with sockets) level of abstraction --- src/server/server.cpp | 20 ++++++++++ src/server/sockets.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ src/server/sockets.hpp | 37 ++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 src/server/server.cpp create mode 100644 src/server/sockets.cpp create mode 100644 src/server/sockets.hpp diff --git a/src/server/server.cpp b/src/server/server.cpp new file mode 100644 index 0000000..6834ceb --- /dev/null +++ b/src/server/server.cpp @@ -0,0 +1,20 @@ +#include + +#include "chat.hpp" + +int main(int argc, char *argv[]) +{ + /* Event-driven programming */ + /* + 1) selection event + 2) event handling + */ + EventSelector *selector = new EventSelector; + /*ChatServer *serv = ChatServer::Start(selector, port); + if(!serv) { + perror("server"); + return 1; + }*/ + selector->Run(); + return 0; +} \ No newline at end of file diff --git a/src/server/sockets.cpp b/src/server/sockets.cpp new file mode 100644 index 0000000..1a52786 --- /dev/null +++ b/src/server/sockets.cpp @@ -0,0 +1,101 @@ +#include + +#include "sockets.hpp" + +#define INVALID_FD -1 + +EventSelector::~EventSelector() +{ + if(fd_array) + delete[] fd_array; + if(fds) + delete[] fds; +} + +void EventSelector::Add(FdHandler *h) +{ + int fd = h->GetFd(); + if(!fd_array) { + fd_array_len = fd > 23 ? fd + 1 : 24; + fd_array = new FdHandler*[fd_array_len]; + // maybe use memset too? + fds = new struct pollfd[fd_array_len]; + + for(int i = 0; i < fd_array_len; i++) { + fd_array[i] = 0; + fds[i] = { INVALID_FD, 0, 0 }; + } + } + if(fd >= fd_array_len) { + FdHandler **tmp_arr = new FdHandler*[fd+1]; + struct pollfd *tmp_fds = new struct pollfd[fd+1]; + + for(int i = 0; i <= fd; i++) { + if(i < fd_array_len) { + tmp_arr[i] = fd_array[i]; + tmp_fds[i] = fds[i]; + } + else { + fd_array[i] = 0; + fds[i] = { INVALID_FD, 0, 0 }; + } + fd_array_len = fd + 1; + + delete[] fd_array; + fd_array = tmp_arr; + delete[] fds; + fds = tmp_fds; + } + } + if(fd > max_fd) + max_fd = fd; + + fd_array[fd] = h; + fds[fd].fd = fd; + if(fd_array[fd]->WantRead()) + fds[fd].events |= POLLIN; + if(fd_array[fd]->WantWrite()) + fds[fd].events |= POLLOUT; +} + +bool EventSelector::Remove(FdHandler *h) +{ + int fd = h->GetFd(); + if(fd >= fd_array_len || fd_array[fd] != h) + return false; + + fd_array[fd] = 0; + fds[fd] = { INVALID_FD, 0, 0 }; + if(fd == max_fd) { + while(max_fd >= 0 && !fd_array[max_fd]) + max_fd--; + } + + return true; +} + +void EventSelector::Run() +{ + exit_flag = false; + do { + int res = poll(fds, max_fd, -1); + + if(res < 0) { + if(errno == EINTR) + continue; + else + break; + } + + if(res > 0) { + for(int i = 0; i <= max_fd; i++) { + if(!fd_array[i]) + continue; + bool r = (fds[i].revents & POLLIN); + bool w = (fds[i].revents & POLLOUT); + if(r || w) + fd_array[i]->Handle(r, w); + } + } + } while(!exit_flag); +} \ No newline at end of file diff --git a/src/server/sockets.hpp b/src/server/sockets.hpp new file mode 100644 index 0000000..2f47e3b --- /dev/null +++ b/src/server/sockets.hpp @@ -0,0 +1,37 @@ +#ifndef SOCKETS_H +#define SOCKETS_H + +#include +#include + +class FdHandler { // abstract class + int fd; +public: + FdHandler(int i_fd) : fd(i_fd) {} + virtual ~FdHandler() { close(fd); } + + int GetFd() const { return fd; } + + virtual bool WantRead() const { return true; } + virtual bool WantWrite() const { return false; } + virtual void Handle(bool r, bool w) = 0; +}; + +class EventSelector { + FdHandler **fd_array; + struct pollfd *fds; + int fd_array_len; + int max_fd; + + bool exit_flag; +public: + EventSelector() : fd_array(0), fds(0), max_fd(-1), exit_flag(false) {} + ~EventSelector(); + + void Add(FdHandler *h); + bool Remove(FdHandler *h); + + void Run(); + void BreakLoop() { exit_flag = true; } +}; +#endif \ No newline at end of file -- cgit v1.2.3-18-g5258