summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoursoir <chat@joursoir.net>2020-11-23 20:07:36 +0300
committerJoursoir <chat@joursoir.net>2020-11-23 20:07:36 +0300
commitcd2decce51c32b8c0531a87ea849e9f8e80db0d3 (patch)
tree7ee12a1ff8ba8ad95036e63dac186d40f97e0a5c
parenta2ee75888739b66b3bd20d2a1f1e465947f1fbc4 (diff)
downloadwant-chat-cd2decce51c32b8c0531a87ea849e9f8e80db0d3.tar.gz
want-chat-cd2decce51c32b8c0531a87ea849e9f8e80db0d3.tar.bz2
want-chat-cd2decce51c32b8c0531a87ea849e9f8e80db0d3.zip
server: add first (work with sockets) level of abstraction
-rw-r--r--src/server/server.cpp20
-rw-r--r--src/server/sockets.cpp101
-rw-r--r--src/server/sockets.hpp37
3 files changed, 158 insertions, 0 deletions
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 <stdio.h>
+
+#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 <errno.h>
+
+#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 <unistd.h>
+#include <sys/poll.h>
+
+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