diff options
| author | tomsmeding <hallo@tomsmeding.nl> | 2015-05-25 14:26:40 +0200 | 
|---|---|---|
| committer | tomsmeding <hallo@tomsmeding.nl> | 2015-05-25 14:26:40 +0200 | 
| commit | 30ca746887a0f7e089ee515e68e80caae1237cd5 (patch) | |
| tree | 1437981e67d6c4777170fa6cffe5927d102ceaab | |
Initial
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | timerserver.cpp | 273 | 
2 files changed, 278 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..791cf3d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +timerserver +timerwp +timerwaypoint +timerstatus +timerstop diff --git a/timerserver.cpp b/timerserver.cpp new file mode 100644 index 0000000..df5389a --- /dev/null +++ b/timerserver.cpp @@ -0,0 +1,273 @@ +#include <iostream> +#include <fstream> +#include <string> +#include <vector> +#include <sstream> +#include <cstdlib> +#include <cstring> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/un.h> + +#define SOCKET_PATH "/tmp/._timer_sock.socket" + +using namespace std; + +enum MessageType { +	MT_STOP, +	MT_STATUS, +	MT_WAYPOINT +}; + +void recvall(unsigned int sock,char *buf,int num){ +	int ret,acc=0; +	do { +		ret=recv(sock,buf+acc,num-acc,0); +		if(ret==-1){ +			perror("recv"); +			exit(1); +		} +		if(ret==0){ //peer closed its side +			close(sock); +			exit(1); +		} +		acc+=ret; +	} while(acc<num); +} + +void sendall(unsigned int sock,const char *buf,int num){ +	int ret,acc=0; +	do { +		ret=send(sock,buf+acc,num-acc,0); +		if(ret==-1){ +			perror("send"); +			exit(1); +		} +		acc+=ret; +	} while(acc<num); +} +void sendall(unsigned int sock,const char *buf){ +	sendall(sock,buf,strlen(buf)); +} + +void addwaypoint(vector<pair<time_t,string>> &waypoints,string desc){ +	time_t tim=time(NULL); +	waypoints.push_back({tim,desc}); +	char *buf=ctime(&tim); +	buf[strlen(buf)-1]='\0'; +	cout<<"Added waypoint on "<<buf<<": "<<desc<<endl; +} + +unsigned int parseUInt32BE(const unsigned char *buf){ +	return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; +} +unsigned int parseUInt32BE(const char *buf){ +	return parseUInt32BE((unsigned char*)buf); +} + +bool strendequ(const char *str,const char *suffix){ +	const int len1=strlen(str),len2=strlen(suffix); +	return len2>len1?false:strcmp(str+len1-len2,suffix)==0; +} + +void unlink_socketpath(void){ +	unlink(SOCKET_PATH); +} + +void sendwaypoints(unsigned int sock,vector<pair<time_t,string>> &waypoints){ +	stringstream ss; +	for(pair<time_t,string> &p : waypoints){ +		char *buf=ctime(&p.first); +		buf[strlen(buf)-1]='\0'; +		ss<<buf<<": "<<p.second<<endl; +	} +	string s=ss.str(); +	int len=s.size(); +	char buf[4]; +	buf[0]=0xff&(len>>24); +	buf[1]=0xff&(len>>16); +	buf[2]=0xff&(len>>8); +	buf[3]=0xff&len; +	sendall(sock,buf,4); +	sendall(sock,s.c_str(),len); +} + +void act_server(void){ +	vector<pair<time_t,string>> waypoints; +	addwaypoint(waypoints,"Start"); +	pid_t pid=fork(); +	if(pid==-1){ +		perror("fork"); +		exit(1); +	} +	if(pid!=0){ //parent +		cerr<<"Forking into background."<<endl; +		exit(0); +	} +	//child, becoming a daemon +	setsid(); +	close(0); close(1); close(2); +	open("/dev/null",O_RDONLY); +	open("/dev/null",O_WRONLY); +	open("/dev/null",O_WRONLY); +	//now we're a daemon. Yay! +	atexit(unlink_socketpath); +	unsigned int s,s2; +	s=socket(AF_UNIX,SOCK_STREAM,0); +	if(s==-1){ +		perror("socket"); +		exit(1); +	} +	struct sockaddr_un local; +	local.sun_family=AF_UNIX; +	strcpy(local.sun_path,SOCKET_PATH); +	if(::bind(s,(struct sockaddr*)&local,strlen(local.sun_path)+1+sizeof(local.sun_family))==-1){ +		perror("bind"); +		exit(1); +	} +	listen(s,2); +	while(true){ +		struct sockaddr_un remote; +		unsigned int len=sizeof(struct sockaddr_un); +		s2=accept(s,(struct sockaddr*)&remote,&len); +		char buf[256]; +		recvall(s2,buf,4); +		unsigned int msglen=parseUInt32BE(buf); +		if(msglen>256){ +			close(s2); +			continue; +		} +		recvall(s2,buf,msglen); +		switch(buf[0]){ +			case MT_STOP: +				addwaypoint(waypoints,"Stop"); +				buf[0]=1; +				sendall(s2,buf,1); +				sendwaypoints(s2,waypoints); +				close(s2); +				close(s); +				exit(0); +			case MT_STATUS: +				buf[0]=1; +				sendall(s2,buf,1); +				sendwaypoints(s2,waypoints); +				break; +			case MT_WAYPOINT: +				addwaypoint(waypoints,string(buf+1,msglen-1)); +				buf[0]=1; +				sendall(s2,buf,1); +				break; +			default: +				buf[0]=0; +				sendall(s2,buf,1); +				break; +		} +	} +} + +unsigned int getclientsock(void){ +	unsigned int s; +	struct sockaddr_un remote; +	s=socket(AF_UNIX,SOCK_STREAM,0); +	if(s==-1){ +		perror("socket"); +		exit(1); +	} +	remote.sun_family=AF_UNIX; +	strcpy(remote.sun_path,SOCKET_PATH); +	if(connect(s,(struct sockaddr*)&remote,strlen(SOCKET_PATH)+1+sizeof(remote.sun_family))==-1){ +		perror("connect"); +		exit(1); +	} +	return s; +} + +void act_client_timerstop(void){ +	unsigned int s=getclientsock(); +	char buf[5]; +	buf[0]=0; +	buf[1]=0; +	buf[2]=0; +	buf[3]=1; +	buf[4]=MT_STOP; +	sendall(s,buf,5); +	recvall(s,buf,1); +	if(buf[0]!=1){ +		cerr<<"Didn't receive acknowledgement from server!"<<endl; +		exit(1); +	} +	recvall(s,buf,4); +	int len=parseUInt32BE(buf); +	char msg[len+1]; +	recvall(s,msg,len); +	msg[len]='\0'; +	cout<<"Results:"<<endl; +	cout<<msg<<flush; +} + +void act_client_timerstatus(void){ +	unsigned int s=getclientsock(); +	char buf[5]; +	buf[0]=0; +	buf[1]=0; +	buf[2]=0; +	buf[3]=1; +	buf[4]=MT_STATUS; +	sendall(s,buf,5); +	recvall(s,buf,1); +	if(buf[0]!=1){ +		cerr<<"Didn't receive acknowledgement from server!"<<endl; +		exit(1); +	} +	recvall(s,buf,4); +	int len=parseUInt32BE(buf); +	char msg[len+1]; +	recvall(s,msg,len); +	msg[len]='\0'; +	cout<<"Status:"<<endl; +	cout<<msg<<flush; +	cout<<"Now:"<<endl; +	time_t tim=time(NULL); +	cout<<ctime(&tim)<<flush; +} + +void act_client_timerwaypoint(void){ +	unsigned int s=getclientsock(); +	cout<<"Enter the description for this waypoint: "<<flush; +	string line; +	getline(cin,line); +	const int buflen=4+1+line.size(); +	char buf[buflen]; +	buf[0]=0; +	buf[1]=0; +	buf[2]=0; +	buf[3]=buflen-4; +	buf[4]=MT_WAYPOINT; +	memcpy(buf+5,line.c_str(),line.size()); +	sendall(s,buf,buflen); +	recvall(s,buf,1); +	if(buf[0]!=1){ +		cerr<<"Didn't receive acknowledgement from server!"<<endl; +		exit(1); +	} +	cout<<"Waypoint added."<<endl; +} + +int main(int argc,char **argv){ +	ios_base::sync_with_stdio(false); +	if(strendequ(argv[0],"timerstop")){ +		act_client_timerstop(); +	} else if(strendequ(argv[0],"timerwaypoint")||strendequ(argv[0],"timerwp")){ +		act_client_timerwaypoint(); +	} else if(strendequ(argv[0],"timerstatus")){ +		act_client_timerstatus(); +	} else if(strendequ(argv[0],"timer")||strendequ(argv[0],"timerserver")){ +		act_server(); +	} else { +		cerr<<"Unknown calling name \""<<argv[0]<<"\"!"<<endl; +		return 1; +	} +	return 0; +}  | 
