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 {  | 
