diff options
-rw-r--r-- | netfs/daemon.cpp | 228 | ||||
-rw-r--r-- | netfs/daemon.h | 8 |
2 files changed, 179 insertions, 57 deletions
diff --git a/netfs/daemon.cpp b/netfs/daemon.cpp index 4876a1a..d9990fe 100644 --- a/netfs/daemon.cpp +++ b/netfs/daemon.cpp @@ -1,6 +1,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> +#include <signal.h> #include <errno.h> #include <string.h> #include <set> @@ -49,73 +50,186 @@ class TempUserChange { } void -runDaemonOn(FILE * f, DaemonConfigPtr, DaemonGlobalStatePtr) +runDaemonOn(FILE * f, DaemonGlobalStatePtr) { - while (true) { - PacketPtr p = new Packet(f); - Sender s(p->index, f); - uint16_t type (p->data->dataTypeID()); - // Dirs - TRYCLASS(OpenDirRequest); - TRYCLASS(CloseDirRequest); - TRYCLASS(ReadDirRequest); - TRYCLASS(RmDirRequest); - TRYCLASS(MkDirRequest); - // Misc - TRYCLASS(AccessRequest); - TRYCLASS(GetAttrRequest); - TRYCLASS(FgetAttrRequest); - TRYCLASS(UnlinkRequest); - TRYCLASS(SymlinkRequest); - TRYCLASS(LinkRequest); - TRYCLASS(RenameRequest); - TRYCLASS(ReadlinkRequest); - TRYCLASS(ChmodRequest); - TRYCLASS(ChownRequest); - // Files - TRYCLASS(OpenRequest); - TRYCLASS(CloseRequest); - TRYCLASS(ReadRequest); - TRYCLASS(WriteRequest); - TRYCLASS(TruncateRequest); - TRYCLASS(FtruncateRequest); - TRYCLASS(CreateRequest); - // FS - TRYCLASS(StatfsRequest); + PacketPtr p = new Packet(f); + Sender s(p->index, f); + uint16_t type (p->data->dataTypeID()); + // Dirs + TRYCLASS(OpenDirRequest); + TRYCLASS(CloseDirRequest); + TRYCLASS(ReadDirRequest); + TRYCLASS(RmDirRequest); + TRYCLASS(MkDirRequest); + // Misc + TRYCLASS(AccessRequest); + TRYCLASS(GetAttrRequest); + TRYCLASS(FgetAttrRequest); + TRYCLASS(UnlinkRequest); + TRYCLASS(SymlinkRequest); + TRYCLASS(LinkRequest); + TRYCLASS(RenameRequest); + TRYCLASS(ReadlinkRequest); + TRYCLASS(ChmodRequest); + TRYCLASS(ChownRequest); + // Files + TRYCLASS(OpenRequest); + TRYCLASS(CloseRequest); + TRYCLASS(ReadRequest); + TRYCLASS(WriteRequest); + TRYCLASS(TruncateRequest); + TRYCLASS(FtruncateRequest); + TRYCLASS(CreateRequest); + // FS + TRYCLASS(StatfsRequest); +} +typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); + +bool running = true; +void onsigint(int, siginfo_t *, void *) +{ + running = false; +} + +void setsignal(int sig, sa_sigaction_t f) +{ + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); + act.sa_sigaction = f; + sigaction(sig, &act, NULL); +} + +class SocketEventHandler : public IsRefCounted { + public: + SocketEventHandler(int sock) : socket(sock) { } + virtual void onRead() { } + virtual void onWrite() { } + virtual void onError() { } + + const int socket; +}; +typedef SmartPointer<SocketEventHandler> SockEvHdlrPtr; +typedef std::map<int, SockEvHdlrPtr> SocketSet; + +class IncomingPacketHandler : public SocketEventHandler { + public: + IncomingPacketHandler(int sock, DaemonGlobalStatePtr d) : SocketEventHandler(sock), dgs(d) + { + f = fdopen(sock, "a+"); + } + void onRead() + { + runDaemonOn(f, dgs); + } + void onError() + { + } + private: + FILE * f; + DaemonGlobalStatePtr dgs; +}; +class ListenAcceptHandler : public SocketEventHandler { + public: + ListenAcceptHandler(int sock, SocketSet & socks, DaemonGlobalStatePtr d) : + SocketEventHandler(sock), sockets(socks), dgs(d) + { + } + void onRead() + { + int fd = accept(socket, NULL, NULL); + sockets[fd] = new IncomingPacketHandler(fd, dgs); + } + private: + SocketSet & sockets; + DaemonGlobalStatePtr dgs; +}; + + +void +createListeners(DaemonGlobalStatePtr dgs, SocketSet & lsocks) +{ + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + struct addrinfo *result, *rp; + if (getaddrinfo(NULL, dgs->config->tcpPort.c_str(), &hints, &result) == 0) { + for (rp = result; rp != NULL; rp = rp->ai_next) { + int sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sfd == -1) { + close(sfd); + continue; + } + if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != 0) { + close(sfd); + continue; + } + if (listen(sfd, 5)) { + close(sfd); + continue; + } + lsocks[sfd] = new ListenAcceptHandler(sfd, lsocks, dgs); + } } - fclose(f); } -int main(int, char* []) +void +listener(DaemonGlobalStatePtr dgs) { - DaemonConfigPtr dc = DaemonConfig::Load("daemon.xml"); - DaemonGlobalStatePtr dgs = new DaemonGlobalState(); - while (true) { - struct addrinfo hints; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - struct addrinfo *result, *rp; - if (getaddrinfo(NULL, dc->tcpPort.c_str(), &hints, &result) == 0) { - for (rp = result; rp != NULL; rp = rp->ai_next) { - int sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sfd == -1) - continue; - if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { - if (listen(sfd, 5)) { - // Error - continue; - } - for (int newfd; (newfd = accept(sfd, NULL, NULL)) > 0; ) { - runDaemonOn(fdopen(newfd, "a+"), dc, dgs); + SocketSet socks; + createListeners(dgs, socks); + if (!socks.size()) { + return; + } + while (running) { + fd_set readSocks; + fd_set errSocks; + FD_ZERO(&readSocks); + FD_ZERO(&errSocks); + int maxfd = 0; + foreach(SocketSet::const_iterator, socks, s) { + FD_SET(s->first, &readSocks); + FD_SET(s->first, &errSocks); + maxfd = std::max(s->first, maxfd); + } + struct timeval to = { 1, 0 }; + int rsel = select(maxfd + 1, &readSocks, NULL, &errSocks, &to); + if (rsel) { + std::set<int> toRemove; + foreach(SocketSet::const_iterator, socks, s) { + if (FD_ISSET(s->first, &errSocks)) { + s->second->onError(); + close(s->first); + toRemove.insert(s->second); + } + else { + if (FD_ISSET(s->first, &readSocks)) { + try { + s->second->onRead(); + } + catch (...) { + } } - break; } - close(sfd); + } + foreach(std::set<int>::const_iterator, toRemove, s) { + socks.erase(*s); } } } + foreach(SocketSet::const_iterator, socks, s) { + close(s->first); + } +} + +int main(int, char* []) +{ + DaemonConfigPtr dc = DaemonConfig::Load("daemon.xml"); + DaemonGlobalStatePtr dgs = new DaemonGlobalState(dc); + setsignal(SIGINT, onsigint); + + listener(dgs); return 0; } diff --git a/netfs/daemon.h b/netfs/daemon.h index 2517529..565ca05 100644 --- a/netfs/daemon.h +++ b/netfs/daemon.h @@ -2,9 +2,17 @@ #define DAEMON_H #include "comms.h" +#include "daemonConfig.h" #include "msgtypes.h" class DaemonGlobalState : public IsRefCounted { + public: + DaemonGlobalState(DaemonConfigPtr c) : + config(c) + { + } + + const DaemonConfigPtr config; }; typedef SmartPointer<DaemonGlobalState> DaemonGlobalStatePtr; class Sender { |