summaryrefslogtreecommitdiff
path: root/server/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/main.c')
-rw-r--r--server/main.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/server/main.c b/server/main.c
new file mode 100644
index 0000000..3cf1ffd
--- /dev/null
+++ b/server/main.c
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#include "global.h"
+#include "data_stream.h"
+#include "line_reader.h"
+#include "zbuffer.h"
+
+#define PORT 57575
+
+#define POLLDELAY (10*1000000)
+
+/*struct proc_taskinfo {
+ uint64_t pti_virtual_size; virtual memory size (bytes)
+ uint64_t pti_resident_size; resident memory size (bytes)
+ uint64_t pti_total_user; total time
+ uint64_t pti_total_system;
+ uint64_t pti_threads_user; existing threads only
+ uint64_t pti_threads_system;
+ int32_t pti_policy; default policy for new threads
+ int32_t pti_faults; number of page faults
+ int32_t pti_pageins; number of actual pageins
+ int32_t pti_cow_faults; number of copy-on-write faults
+ int32_t pti_messages_sent; number of messages sent
+ int32_t pti_messages_received; number of messages received
+ int32_t pti_syscalls_mach; number of mach system calls
+ int32_t pti_syscalls_unix; number of unix system calls
+ int32_t pti_csw; number of context switches
+ int32_t pti_threadnum; number of threads in the task
+ int32_t pti_numrunning; number of running threads
+ int32_t pti_priority; task priority
+};*/
+
+static i64 make_timestamp(void){
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return tv.tv_sec*(i64)1000000+tv.tv_usec;
+}
+
+static void connection_handler(int sock){
+ struct data_stream *stream=data_stream_init(sock);
+ struct line_reader *reader=line_reader_init(sock);
+
+ i64 polldelay=POLLDELAY;
+ i64 timeleft=polldelay;
+
+ bool do_send_frames=false;
+
+ bool do_quit=false;
+
+ while(true){
+ struct timeval timeout={timeleft/1000000,timeleft%1000000};
+ i64 before=make_timestamp();
+
+ fd_set inset;
+ FD_ZERO(&inset);
+ FD_SET(sock,&inset);
+ int ret=select(sock+1,&inset,NULL,NULL,do_send_frames?&timeout:NULL);
+ if(ret<0){
+ if(errno==EINTR)continue;
+ perror("select");
+ break;
+ }
+ if(ret==0||!FD_ISSET(sock,&inset)){ // timeout
+ if(do_send_frames){
+ if(data_stream_frame(stream)<0){
+ printf("Error sending data\n");
+ goto cleanup;
+ }
+ printf("."); fflush(stdout);
+ }
+ timeleft=polldelay;
+ continue;
+ }
+
+ i64 after=make_timestamp();
+ if(after<before){
+ printf("Time ran backwards?\n");
+ after=before;
+ }
+ timeleft-=after-before;
+ if(timeleft<0)timeleft=0;
+
+ char buf[1024];
+ i64 nr=read(sock,buf,sizeof buf);
+ if(nr<0){
+ if(errno==EINTR)continue;
+ perror("read");
+ break;
+ }
+ if(nr==0)break; // EOF
+ line_reader_supply_data(reader,buf,nr);
+
+ char *line;
+ while((line=line_reader_get_line(reader,false))!=NULL){
+ char *word=line;
+
+ printf("Read <%s>\n",line);
+
+ char *next=strchr(word,' ');
+ if(next!=NULL){
+ *next='\0';
+ next++;
+ }
+ if(strcmp(word,"delay")==0){
+ char *endp;
+ i64 v=strtoll(next,&endp,10);
+ if(*next=='\0'||*endp!='\0'||v<=1000){
+ free(line);
+ printf("Invalid number in delay\n");
+ continue;
+ }
+ polldelay=v;
+ printf("polldelay -> %" PRIi64 "\n",polldelay);
+ if(timeleft>polldelay)timeleft=polldelay;
+ } else if(strcmp(word,"start")==0){
+ do_send_frames=true;
+ printf("Sending enabled\n");
+ } else if(strcmp(word,"stop")==0){
+ do_send_frames=false;
+ printf("Sending disabled\n");
+ } else if(strcmp(word,"flush")==0){
+ printf("Flushing\n");
+ if(data_stream_flush(stream)<0){
+ printf("Error flushing\n");
+ goto cleanup;
+ }
+ } else if(strcmp(word,"quit")==0){
+ printf("Quitting by request\n");
+ do_quit=true;
+ goto cleanup;
+ } else {
+ printf("Read unrecognised line <%s>!\n",line);
+ }
+
+ free(line);
+ }
+ }
+
+cleanup:
+ data_stream_finish_destroy(stream);
+ if(do_quit)exit(0);
+}
+
+int main(void){
+ int sock=socket(PF_INET,SOCK_STREAM,0);
+ if(sock<0){
+ perror("socket");
+ return 1;
+ }
+
+ int one=1;
+ if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(int))<0){
+ perror("setsockopt");
+ return 1;
+ }
+
+ struct sockaddr_in sin;
+ sin.sin_family=AF_INET;
+ sin.sin_addr.s_addr=htonl(INADDR_ANY);
+ sin.sin_port=htons(PORT);
+
+ if(bind(sock,(struct sockaddr*)&sin,sizeof(sin))<0){
+ close(sock);
+ perror("bind");
+ return 1;
+ }
+
+ if(listen(sock,1)<0){
+ perror("listen");
+ return 1;
+ }
+
+ printf("Listening on port %d\n",PORT);
+
+ while(true){
+ struct sockaddr_storage client_addr;
+ socklen_t client_addr_sz=sizeof(client_addr);
+ int clientsock=accept(sock,(struct sockaddr*)&client_addr,&client_addr_sz);
+ if(clientsock<0){
+ perror("accept");
+ continue;
+ }
+
+ char str[INET_ADDRSTRLEN];
+ inet_ntop(client_addr.ss_family,&((struct sockaddr_in*)&client_addr)->sin_addr,
+ str,sizeof(str));
+
+ printf("Accept from %s\n",str);
+ connection_handler(clientsock);
+ close(clientsock);
+ }
+}