From 36ad6ac957f2f6161c1ac4345a0004b7b6249ce5 Mon Sep 17 00:00:00 2001
From: "Garcia-Hernandez, Ruben Jesus (rgarcia)" <garcia@lrz.de>
Date: Tue, 15 May 2018 11:42:10 +0200
Subject: [PATCH] Early multiuser support for HTC Vive. World status is saved
 in server.

---
 OpenVR/TimestepData/hellovr_opengl_main.cpp | 135 ++++++++++++++++----
 proxy/Makefile                              |   2 +-
 proxy/proxy.cpp                             |  81 ++++++++++--
 3 files changed, 178 insertions(+), 40 deletions(-)

diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp
index ebbbaca..8f8eeda 100644
--- a/OpenVR/TimestepData/hellovr_opengl_main.cpp
+++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp
@@ -257,6 +257,8 @@ private: // OpenGL bookkeeping
 
 
 	int currentset;
+	void IncrementTimestep();
+	void DecrementTimestep();
 	float elapsedtime;
 	static const float videospeed;
 	int currentiso;
@@ -353,6 +355,13 @@ private: // OpenGL bookkeeping
 	std::thread *tcpconn;
 	void connectTCP();
 	int sock;
+	void Send(char c, int32_t value);
+	void Send(char c, bool value);
+	void SendConfigFile();
+	void SendTimestep();
+	void SendIso();
+	void SendShowAtoms();
+
 };
 
 const float CMainApplication::videospeed = 0.01f;
@@ -453,6 +462,7 @@ void CMainApplication::connectTCP()
 	struct sockaddr_in serv_addr;
 	struct hostent *he;
 	if ( (he = gethostbyname(server) ) == nullptr ) {
+		eprintf ("Connect to server, could not get host name %s\n", server);
       return; /* error */
 	}
 	memset((char *) &serv_addr, 0, sizeof(serv_addr));
@@ -461,6 +471,7 @@ void CMainApplication::connectTCP()
 	serv_addr.sin_port = htons(port);
 	sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 	if ( connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
+				eprintf ("Connect to server, could not get connection %s\n", server);
       return; /* error */
 	}
 	//read state
@@ -473,32 +484,42 @@ void CMainApplication::connectTCP()
 	char what;
 	while (true) {
 		n=recv(sock, &what, sizeof(what), 0);
-		if (n<1)
+		if (n<1) {
+			eprintf ("closed socket\n");
 			return;
+		}
 		switch (what) {
 		case 't':
 			n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
-			if (n<sizeof(tmp))
+			if (n<sizeof(tmp)) {
+				eprintf ("short read at socket\n");
 				return;
+			}
 			currentset=ntohl(tmp)%TIMESTEPS;
 			break;
 		case 'i':
 			n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
-			if (n<sizeof(tmp))
+			if (n<sizeof(tmp)) {
+				eprintf ("short read at socket\n");
 				return;
+			}
 			currentiso=ntohl(tmp)%(ISOS+1);
 			break;
 		case 's':
 			char s;
 			n=recv (sock, &s, sizeof(s), 0);
-			if (n<sizeof(s))
+			if (n<sizeof(s)) {
+				eprintf ("short read at socket\n");
 				return;
+			}
 			showAtoms=(bool)s;
 			break;
 		case 'n':
 			n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
-			if (n<sizeof(tmp))
+			if (n<sizeof(tmp)) {
+				eprintf ("short read at socket\n");
 				return;
+			}
 			//load config file
 			if (currentConfig!=ntohl(tmp)%myargc) {
 				currentConfig=ntohl(tmp)%myargc;
@@ -980,6 +1001,76 @@ void CMainApplication::Shutdown()
 	SDL_Quit();
 }
 
+void CMainApplication::Send(char c, int32_t value)
+{
+	if (sock>=0) {
+		int32_t tmp;
+		tmp=htonl(value);
+		int n;
+		n=send(sock, &c, sizeof(c), 0);
+		if (n<sizeof(c)) {
+			closesocket(sock);
+			sock=-1;
+		}
+		n=send(sock, (char*)&tmp, sizeof(tmp), 0);
+		if (n<sizeof(tmp)) {
+			closesocket(sock);
+			sock=-1;
+		}
+	}
+}
+
+void CMainApplication::Send(char c, bool value)
+{
+	if (sock>=0) {
+		int n;
+		n=send(sock, &c, sizeof(c), 0);
+		if (n<sizeof(c)) {
+			closesocket(sock);
+			sock=-1;
+		}
+		n=send(sock, (char*)&value, 1, 0);
+		if (n<1) {
+			closesocket(sock);
+			sock=-1;
+		}
+	}
+}
+void CMainApplication::SendConfigFile()
+{
+	Send('n', currentConfig);
+}
+
+void CMainApplication::SendTimestep()
+{
+	Send('t', currentset);
+}
+
+void CMainApplication::SendIso()
+{
+	Send('i', currentiso);
+}
+
+void CMainApplication::SendShowAtoms()
+{
+	Send('s', showAtoms);
+}
+
+void CMainApplication::IncrementTimestep()
+{
+	currentset++;
+	if (currentset >= TIMESTEPS)
+		currentset = 0;
+	SendTimestep();
+}
+
+void CMainApplication::DecrementTimestep()
+{
+currentset--;
+if (currentset < 0)
+	currentset = TIMESTEPS -1;
+SendTimestep();
+}
 //-----------------------------------------------------------------------------
 // Purpose:
 //-----------------------------------------------------------------------------
@@ -1012,19 +1103,16 @@ bool CMainApplication::HandleInput()
 			}
 			//rgh: add keyboard navigation here
 			if (sdlEvent.key.keysym.sym == SDLK_1) {
-				currentset++;
-				if (currentset >= TIMESTEPS)
-					currentset = 0;
+				IncrementTimestep();
 			}
 			if (sdlEvent.key.keysym.sym == SDLK_2) {
-				currentset--;
-				if (currentset < 0)
-					currentset = TIMESTEPS -1;
+				DecrementTimestep();
 			}
 			if (sdlEvent.key.keysym.sym == SDLK_0) {
 				currentiso++;
 				if (currentiso > ISOS)
 					currentiso = 0;
+				SendIso();
 			}
 			if (sdlEvent.key.keysym.sym == SDLK_a) {
 				Matrix4 tmp = m_mat4HMDPose;
@@ -1089,22 +1177,7 @@ bool CMainApplication::HandleInput()
 						currentConfig++;
 						if (currentConfig>=myargc)
 							currentConfig=1;
-						if (sock>=0) {
-							char w='c';
-							int32_t tmp;
-							tmp=htonl(currentConfig);
-							int n;
-							n=send(sock, &w, sizeof(w), 0);
-							if (n<sizeof(w)) {
-								closesocket(sock);
-								sock=-1;
-							}
-							n=send(sock, (char*)&tmp, sizeof(tmp), 0);
-							if (n<sizeof(tmp)) {
-								closesocket(sock);
-								sock=-1;
-							}
-						}
+						SendConfigFile();
 						CleanScene();
 						LoadConfigFile(myargv[currentConfig]);
 						SetupScene();
@@ -1113,6 +1186,7 @@ bool CMainApplication::HandleInput()
 						currentConfig--;
 						if (currentConfig<=0)
 							currentConfig=myargc-1;
+						SendConfigFile();
 						CleanScene();
 						LoadConfigFile(myargv[currentConfig]);
 						SetupScene();
@@ -1131,8 +1205,10 @@ bool CMainApplication::HandleInput()
 */
 				if (firstdevice==unDevice)
 					savetodisk = !savetodisk;
-				else
+				else {
 					showAtoms= !showAtoms;
+					SendShowAtoms();
+				}
 			}
 			else if (buttonPressed[1][unDevice] && 
 				0 == (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) &&
@@ -1161,10 +1237,12 @@ bool CMainApplication::HandleInput()
 						currentset = TIMESTEPS - 1;
 					else if (currentset > TIMESTEPS - 1)
 						currentset=0;
+					SendTimestep();
 				} else {
 					currentiso++;
 					if (currentiso > ISOS)
 						currentiso = 0;
+					SendIso();
 				}
 			} else if (buttonPressed[0][unDevice] && (
 				(state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip)) == 0 &&
@@ -1197,6 +1275,7 @@ bool CMainApplication::HandleInput()
 						currentset++;
 						if (currentset >= TIMESTEPS)
 							currentset = 0;
+						SendTimestep();
 					}
 				}
 			}
diff --git a/proxy/Makefile b/proxy/Makefile
index 7fcc2cd..15fd70c 100644
--- a/proxy/Makefile
+++ b/proxy/Makefile
@@ -1,5 +1,5 @@
 proxy:	proxy.cpp Makefile
-	g++ -g proxy.cpp -o proxy
+	g++ -std=c++11 -g proxy.cpp -o proxy
 
 clean:
 	rm -f proxy.o proxy
diff --git a/proxy/proxy.cpp b/proxy/proxy.cpp
index f7a06b2..561295f 100644
--- a/proxy/proxy.cpp
+++ b/proxy/proxy.cpp
@@ -74,7 +74,7 @@ bool initNewSocket (unsigned int secret)
 	 tmp=htonl(state.iso);
 	 memcpy (buffer+6, &tmp, sizeof(state.iso));
 	 buffer[10]='s';
-	 buffer[11]=(char)true;
+	 buffer[11]=(char)state.showatoms;
 	 buffer[12]='n';
 	 tmp=htonl(state.ncfg);
 	 memcpy (buffer+13, &tmp, sizeof(state.iso));
@@ -110,6 +110,20 @@ bool initNewSocket (unsigned int secret)
 	return true;
 }
 
+int myrecv(int sock,char *buffer,int len, int flags) {
+	int n=len;
+	char *mybuff=buffer;
+	int r;
+	do {
+		r=recv (sock, mybuff, n, flags);
+		if (r<0)
+			return r;
+		mybuff+=r;
+		n-=r;
+	} while (n>0);
+	return len;
+}
+
 int main(int argc, char *argv[])
 {
 	unsigned int secret;
@@ -205,45 +219,90 @@ for (;;) {
 
 	for (unsigned i=1;i<sockfds.size();i++)
 		if (FD_ISSET (sockfds[i], &read_fd_set)) {
-     		n = recv(sockfds[i],buffer,255, 0);
+     		n = myrecv(sockfds[i],buffer,1, 0);
+			fprintf (stderr, "received %d bytes from socket %d\n", n, i);
+			if (n<0) { //disconnected
+				printf  ("client closed socket\n");
+				sockfds[i]=-1;
+				continue;
+			}
 			buffer[n]=0;
-			if (n < 0) error("ERROR reading from socket");
-			if (n==0) error ("client closed socket, exiting");
+			if (n==0) {
+				printf  ("client closed socket\n");
+				sockfds[i]=-1;
+				continue;
+			}
 
-			printf("Here is the message: %s\n",buffer);
+			printf("Here is the message: '%s'\n",buffer);
+		
 			//update state
 			if (buffer[0]=='t') {
+				n = myrecv(sockfds[i],buffer+1,4, 0);
+				if (n<0) { //disconnected
+					sockfds[i]=-1;
+					continue;
+				}
 				int32_t time;
 				memcpy(&time, buffer+1, sizeof(int32_t));
 				time=ntohl(time);
 				state.timestep=time;
+				printf("Timestep: %d\n",time);
 			} else if (buffer[0]=='i') {
+				n = myrecv(sockfds[i],buffer+1,4, 0);
+				if (n<0) { //disconnected
+					sockfds[i]=-1;
+					continue;
+				}
 				int32_t iso;
 				memcpy(&iso, buffer+1, sizeof(int32_t));
 				iso=ntohl(iso);
-				state.timestep=iso;
+				state.iso=iso;
+				printf("Iso: %d\n",iso);
 			} else if (buffer[0]=='n') {
+				n = myrecv(sockfds[i],buffer+1,4, 0);
+				if (n<0) { //disconnected
+					sockfds[i]=-1;
+					continue;
+				}
 				int32_t ncfg;
 				memcpy(&ncfg, buffer+1, sizeof(int32_t));
 				ncfg=ntohl(ncfg);
-				state.timestep=ncfg;
+				state.ncfg=ncfg;
+				printf("ncfg: %d\n",ncfg);
 			} else if (buffer[0]=='s') {
+				n = myrecv(sockfds[i],buffer+1,1, 0);
+				if (n<0) { //disconnected
+					sockfds[i]=-1;
+					continue;
+				}
 				state.showatoms=buffer[1]!=0;
+				printf("showatoms: %d\n",state.showatoms);
 			} else {
-				fprintf (stderr, "Unknown state request %c\n", buffer[0]);
+				fprintf (stderr, "Unknown state request '%c'\n", buffer[0]);
 				error ("unknown state" );
 			}
 
 			for (unsigned j=1;j<sockfds.size();j++) {
-				n = send(sockfds[j], buffer , n, 0);
-				if (n < 0) error("ERROR writing to socket");
+				if (sockfds[j]>=0) {
+					if (buffer[0]=='s')
+						n=2;
+					else 
+						n=5;
+					n = send(sockfds[j], buffer , n, 0);
+					if (n < 0) {
+						fprintf(stderr, "ERROR writing to socket, closing\n");
+						sockfds[j]=-1;
+					}
+				}
 			}
 		}
 
 	//unblockingly see if new connections were made and add to sockfds
 	if (FD_ISSET (sockfds[0], &read_fd_set)) {
-		if (initNewSocket (secret));
+		if (initNewSocket (secret)) {
+			printf ("Connected to new client\n");
 			FD_SET (sockfds.back(), &active_fd_set);
+		}
 	}
 }
 #ifdef WIN32
-- 
GitLab