From 20be24a0baa2135c5fd4ddacdb76d3af2c5f3235 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 8 Jul 2018 18:12:24 +0100 Subject: WIP --- icespider/embedded/clientSocket.cpp | 55 +++++++++++++++ icespider/embedded/clientSocket.h | 33 +++++++++ icespider/embedded/embedded.cpp | 125 +---------------------------------- icespider/embedded/embedded.h | 69 ++----------------- icespider/embedded/listenSocket.cpp | 32 +++++++++ icespider/embedded/listenSocket.h | 20 ++++++ icespider/embedded/socketEvents.h | 19 ++++++ icespider/embedded/socketHandler.cpp | 39 +++++++++++ icespider/embedded/socketHandler.h | 28 ++++++++ 9 files changed, 234 insertions(+), 186 deletions(-) create mode 100644 icespider/embedded/clientSocket.cpp create mode 100644 icespider/embedded/clientSocket.h create mode 100644 icespider/embedded/listenSocket.cpp create mode 100644 icespider/embedded/listenSocket.h create mode 100644 icespider/embedded/socketEvents.h create mode 100644 icespider/embedded/socketHandler.cpp create mode 100644 icespider/embedded/socketHandler.h diff --git a/icespider/embedded/clientSocket.cpp b/icespider/embedded/clientSocket.cpp new file mode 100644 index 0000000..73aa3cf --- /dev/null +++ b/icespider/embedded/clientSocket.cpp @@ -0,0 +1,55 @@ +#include "clientSocket.h" +#include +#include +#include + +namespace IceSpider::Embedded { + static socklen_t clientlen = sizeof(struct sockaddr_in); + + ClientSocket::ClientSocket(int pfd) : + SocketHandler(accept(pfd, (struct sockaddr *) &clientaddr, &clientlen)), + buf(BUFSIZ), + rec(0), + state(State::reading_headers) + { + } + + FdSocketEventResultFuture ClientSocket::read(Listener * listener) + { + Work w([this]() { + if (buf.size() == rec) { + buf.resize(rec * 2); + } + auto r = ::read(fd, &buf.at(rec), buf.size() - rec); + if (r < 1) { + return FDSetChange::Remove; + } + switch (state) { + case State::reading_headers: + read_headers(r); + break; + case State::streaming_input: + stream_input(r); + break; + } + return FDSetChange::NoChange; + }); + return returnQueued(listener, fd, std::move(w)); + } + + void ClientSocket::read_headers(int r) + { + buf[rec + r] = 0; + if (strstr(&buf.at(rec > 3 ? rec - 2 : 0), "\r\n")) { + auto w = ::write(fd, "HTTP/1.1 204 No content\r\n\r\n", 27); + (void)w; + rec = 0; + } + rec += r; + } + + void ClientSocket::stream_input(int) + { + } +} + diff --git a/icespider/embedded/clientSocket.h b/icespider/embedded/clientSocket.h new file mode 100644 index 0000000..0d6d526 --- /dev/null +++ b/icespider/embedded/clientSocket.h @@ -0,0 +1,33 @@ +#ifndef ICESPIDER_EMBEDDED_CLIENTSOCKET_H +#define ICESPIDER_EMBEDDED_CLIENTSOCKET_H + +#include "socketHandler.h" +#include +#include + +namespace IceSpider::Embedded { + class ClientSocket : public SocketHandler { + public: + ClientSocket(int fd); + + FdSocketEventResultFuture read(Listener * listener) override; + + private: + inline void read_headers(int bytes); + inline void stream_input(int bytes); + + enum class State { + reading_headers, + streaming_input, + }; + + struct sockaddr_in clientaddr; + std::vector buf; + std::size_t rec; + State state; + }; + +} + +#endif + diff --git a/icespider/embedded/embedded.cpp b/icespider/embedded/embedded.cpp index 9b65839..2b1cfcd 100644 --- a/icespider/embedded/embedded.cpp +++ b/icespider/embedded/embedded.cpp @@ -1,123 +1,7 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include "embedded.h" -#include -#include -#include -#include - -static socklen_t clientlen = sizeof(struct sockaddr_in); +#include "listenSocket.h" namespace IceSpider::Embedded { - SocketHandler::SocketHandler(int f) : - fd(f) - { - if (fd < 0) { - throw std::runtime_error("Invalid socket"); - } - } - - SocketHandler::~SocketHandler() - { - close(fd); - } - - FdSocketEventResultFuture SocketHandler::returnNow(int fd, const SocketEventResult && ser) - { - std::promise p; - p.set_value(ser); - return { fd, p.get_future() }; - } - - FdSocketEventResultFuture SocketHandler::returnQueued(Listener * listener, int fd, Work && work) - { - auto f = work.get_future(); - BOOST_VERIFY_MSG(listener->work.try_enqueue(std::move(work)), "try_enqueue"); - return { fd, std::move(f) }; - } - - FdSocketEventResultFuture SocketHandler::except(Listener *) - { - return returnNow(fd, FDSetChange::Remove); - } - - ClientSocket::ClientSocket(int pfd) : - SocketHandler(accept(pfd, (struct sockaddr *) &clientaddr, &clientlen)), - buf(BUFSIZ), - rec(0), - state(State::reading_headers) - { - } - - FdSocketEventResultFuture ClientSocket::read(Listener * listener) - { - Work w([this]() { - if (buf.size() == rec) { - buf.resize(rec * 2); - } - auto r = ::read(fd, &buf.at(rec), buf.size() - rec); - if (r < 1) { - return FDSetChange::Remove; - } - switch (state) { - case State::reading_headers: - read_headers(r); - break; - case State::streaming_input: - stream_input(r); - break; - } - return FDSetChange::NoChange; - }); - return returnQueued(listener, fd, std::move(w)); - } - - void ClientSocket::read_headers(int r) - { - buf[rec + r] = 0; - if (strstr(&buf.at(rec > 3 ? rec - 2 : 0), "\r\n")) { - auto w = ::write(fd, "HTTP/1.1 204 No content\r\n\r\n", 27); - (void)w; - rec = 0; - } - rec += r; - } - - void ClientSocket::stream_input(int) - { - } - - ListenSocket::ListenSocket(unsigned short portno) : - SocketHandler(socket(AF_INET, SOCK_STREAM, 0)) - { - int optval = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)); - - bzero(&serveraddr, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); - serveraddr.sin_port = htons(portno); - - if (bind(fd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) { - throw std::runtime_error("ERROR on binding"); - } - - if (listen(fd, 5) < 0) { - throw std::runtime_error("ERROR on listen"); - } - } - - FdSocketEventResultFuture ListenSocket::read(Listener * listener) - { - return returnNow(listener->create(fd), FDSetChange::AddNew); - } - Listener::Listener() : work(1024), topSock(0) @@ -213,13 +97,6 @@ namespace IceSpider::Embedded { } } - template inline int Listener::create(const P & ... p) - { - auto s = std::make_unique(p...); - topSock = std::max(s->fd + 1, topSock); - return (sockets[s->fd] = std::move(s))->fd; - } - void Listener::add(int fd) { FD_SET(fd, &rfds); diff --git a/icespider/embedded/embedded.h b/icespider/embedded/embedded.h index 08f280a..7d7fafa 100644 --- a/icespider/embedded/embedded.h +++ b/icespider/embedded/embedded.h @@ -1,75 +1,15 @@ #ifndef ICESPIDER_EMBEDDED_H #define ICESPIDER_EMBEDDED_H -#include -#include #include #include #include #include -#include #include #include +#include "socketHandler.h" namespace IceSpider::Embedded { - class Listener; - - enum class FDSetChange { - NoChange, - AddNew, - Remove, - }; - typedef std::tuple SocketEventResult; - typedef std::future SocketEventResultFuture; - typedef std::tuple FdSocketEventResultFuture; - - class SocketHandler { - public: - typedef std::packaged_task Work; - - SocketHandler(int f); - ~SocketHandler(); - - static inline FdSocketEventResultFuture returnNow(int, const SocketEventResult &&); - static inline FdSocketEventResultFuture returnQueued(Listener *, int, Work &&); - - virtual FdSocketEventResultFuture read(Listener *) = 0; - virtual FdSocketEventResultFuture except(Listener *); - - const int fd; - }; - - class ClientSocket : public SocketHandler { - public: - ClientSocket(int fd); - - FdSocketEventResultFuture read(Listener * listener) override; - - private: - inline void read_headers(int bytes); - inline void stream_input(int bytes); - - enum class State { - reading_headers, - streaming_input, - }; - - struct sockaddr_in clientaddr; - std::vector buf; - std::size_t rec; - State state; - }; - - class ListenSocket : public SocketHandler { - public: - ListenSocket(unsigned short portno); - - FdSocketEventResultFuture read(Listener * listener) override; - - private: - struct sockaddr_in serveraddr; - }; - class DLL_PUBLIC Listener { public: typedef moodycamel::BlockingConcurrentQueue WorkQueue; @@ -83,7 +23,12 @@ namespace IceSpider::Embedded { void run(); - template inline int create(const P & ... p); + template inline int create(const P & ... p) + { + auto s = std::make_unique(p...); + topSock = std::max(s->fd + 1, topSock); + return (sockets[s->fd] = std::move(s))->fd; + } WorkQueue work; diff --git a/icespider/embedded/listenSocket.cpp b/icespider/embedded/listenSocket.cpp new file mode 100644 index 0000000..945ba43 --- /dev/null +++ b/icespider/embedded/listenSocket.cpp @@ -0,0 +1,32 @@ +#include "listenSocket.h" +#include "embedded.h" +#include "clientSocket.h" +#include + +namespace IceSpider::Embedded { + ListenSocket::ListenSocket(unsigned short portno) : + SocketHandler(socket(AF_INET, SOCK_STREAM, 0)) + { + int optval = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)); + + memset(&serveraddr, 0, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = htons(portno); + + if (bind(fd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) { + throw std::runtime_error("ERROR on binding"); + } + + if (listen(fd, 5) < 0) { + throw std::runtime_error("ERROR on listen"); + } + } + + FdSocketEventResultFuture ListenSocket::read(Listener * listener) + { + return returnNow(listener->create(fd), FDSetChange::AddNew); + } +} + diff --git a/icespider/embedded/listenSocket.h b/icespider/embedded/listenSocket.h new file mode 100644 index 0000000..36a704f --- /dev/null +++ b/icespider/embedded/listenSocket.h @@ -0,0 +1,20 @@ +#ifndef ICESPIDER_EMBEDDED_LISTENSOCKET_H +#define ICESPIDER_EMBEDDED_LISTENSOCKET_H + +#include "socketHandler.h" +#include + +namespace IceSpider::Embedded { + class ListenSocket : public SocketHandler { + public: + ListenSocket(unsigned short portno); + + FdSocketEventResultFuture read(Listener * listener) override; + + private: + struct sockaddr_in serveraddr; + }; +} + +#endif + diff --git a/icespider/embedded/socketEvents.h b/icespider/embedded/socketEvents.h new file mode 100644 index 0000000..9f94d04 --- /dev/null +++ b/icespider/embedded/socketEvents.h @@ -0,0 +1,19 @@ +#ifndef ICESPIDER_EMBEDDED_SOCKETEVENTS_H +#define ICESPIDER_EMBEDDED_SOCKETEVENTS_H + +#include +#include + +namespace IceSpider::Embedded { + enum class FDSetChange { + NoChange, + AddNew, + Remove, + }; + typedef std::tuple SocketEventResult; + typedef std::future SocketEventResultFuture; + typedef std::tuple FdSocketEventResultFuture; +} + +#endif + diff --git a/icespider/embedded/socketHandler.cpp b/icespider/embedded/socketHandler.cpp new file mode 100644 index 0000000..7d93afd --- /dev/null +++ b/icespider/embedded/socketHandler.cpp @@ -0,0 +1,39 @@ +#include "socketHandler.h" +#include "embedded.h" +#include +#include + +namespace IceSpider::Embedded { + SocketHandler::SocketHandler(int f) : + fd(f) + { + if (fd < 0) { + throw std::runtime_error("Invalid socket"); + } + } + + SocketHandler::~SocketHandler() + { + close(fd); + } + + FdSocketEventResultFuture SocketHandler::returnNow(int fd, const SocketEventResult && ser) + { + std::promise p; + p.set_value(ser); + return { fd, p.get_future() }; + } + + FdSocketEventResultFuture SocketHandler::returnQueued(Listener * listener, int fd, Work && work) + { + auto f = work.get_future(); + BOOST_VERIFY_MSG(listener->work.try_enqueue(std::move(work)), "try_enqueue"); + return { fd, std::move(f) }; + } + + FdSocketEventResultFuture SocketHandler::except(Listener *) + { + return returnNow(fd, FDSetChange::Remove); + } +} + diff --git a/icespider/embedded/socketHandler.h b/icespider/embedded/socketHandler.h new file mode 100644 index 0000000..67f5a36 --- /dev/null +++ b/icespider/embedded/socketHandler.h @@ -0,0 +1,28 @@ +#ifndef ICESPIDER_EMBEDDED_SOCKETHANDLER_H +#define ICESPIDER_EMBEDDED_SOCKETHANDLER_H + +#include +#include "socketEvents.h" + +namespace IceSpider::Embedded { + class Listener; + + class SocketHandler { + public: + typedef std::packaged_task Work; + + SocketHandler(int f); + ~SocketHandler(); + + static FdSocketEventResultFuture returnNow(int, const SocketEventResult &&); + static FdSocketEventResultFuture returnQueued(Listener *, int, Work &&); + + virtual FdSocketEventResultFuture read(Listener *) = 0; + virtual FdSocketEventResultFuture except(Listener *); + + const int fd; + }; +} + +#endif + -- cgit v1.2.3