summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-05-25 14:26:40 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-05-25 14:26:40 +0200
commit30ca746887a0f7e089ee515e68e80caae1237cd5 (patch)
tree1437981e67d6c4777170fa6cffe5927d102ceaab
Initial
-rw-r--r--.gitignore5
-rw-r--r--timerserver.cpp273
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;
+}