Module Name:    src
Committed By:   reinoud
Date:           Sat Dec 31 12:38:56 UTC 2011

Modified Files:
        src/sys/arch/usermode/usermode: thunk.c

Log Message:
Implement safe_recv() in analog to save_send() to make sure we don't miss
bytes along and mess up the protocol.


To generate a diff of this commit:
cvs rdiff -u -r1.68 -r1.69 src/sys/arch/usermode/usermode/thunk.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/usermode/usermode/thunk.c
diff -u src/sys/arch/usermode/usermode/thunk.c:1.68 src/sys/arch/usermode/usermode/thunk.c:1.69
--- src/sys/arch/usermode/usermode/thunk.c:1.68	Fri Dec 30 21:14:58 2011
+++ src/sys/arch/usermode/usermode/thunk.c	Sat Dec 31 12:38:56 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: thunk.c,v 1.68 2011/12/30 21:14:58 reinoud Exp $ */
+/* $NetBSD: thunk.c,v 1.69 2011/12/31 12:38:56 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2011 Jared D. McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __NetBSD__
-__RCSID("$NetBSD: thunk.c,v 1.68 2011/12/30 21:14:58 reinoud Exp $");
+__RCSID("$NetBSD: thunk.c,v 1.69 2011/12/31 12:38:56 reinoud Exp $");
 #endif
 
 #include <sys/types.h>
@@ -897,7 +897,7 @@ thunk_rfb_open(thunk_rfb_t *rfb, uint16_
 	return 0;
 }
 
-static int
+static ssize_t
 safe_send(int s, const void *msg, size_t len)
 {
 	const uint8_t *p;
@@ -916,6 +916,25 @@ safe_send(int s, const void *msg, size_t
 	return 0;
 }
 
+static ssize_t
+safe_recv(int s, void *buf, size_t len)
+{
+	uint8_t *p;
+	int recv_len;
+
+	p = buf;
+	while (len) {
+		assert(len >= 0);
+		recv_len = recv(s, p, len, MSG_NOSIGNAL);
+		if (recv_len < 0) 
+			return -1;
+	
+		p   += recv_len;
+		len -= recv_len;
+	}
+	return 0;
+}
+
 static int
 thunk_rfb_server_init(thunk_rfb_t *rfb)
 {
@@ -960,11 +979,9 @@ thunk_rfb_handshake(thunk_rfb_t *rfb)
 
 	/* receive client protocol version */
 	do {
-		len = recv(rfb->clientfd, &dummy, sizeof(dummy), MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd, &dummy, sizeof(dummy));
 		if (len < 0)
 			return errno;
-		if (len == 0)
-			return EIO;
 	} while (dummy != '\n');
 
 	/* send security capabilities */
@@ -974,9 +991,8 @@ thunk_rfb_handshake(thunk_rfb_t *rfb)
 		return errno;
 
 	/* receive client init message */
-	len = recv(rfb->clientfd, &shared_flag, sizeof(shared_flag),
-		MSG_NOSIGNAL);
-	if (len <= 0)
+	len = safe_recv(rfb->clientfd, &shared_flag, sizeof(shared_flag));
+	if (len < 0)
 		return errno;
 
 	/* send server init message */
@@ -1168,11 +1184,11 @@ thunk_rfb_poll(thunk_rfb_t *rfb, thunk_r
 	if (rfb->clientfd == -1)
 		return -1;
 
-	thunk_rfb_send_pending(rfb);
-
 	if (event == NULL)
 		return 0;
 
+	thunk_rfb_send_pending(rfb);
+
 	if (rfb->schedule_bell) {
 		uint8_t msg_type = 2;	/* bell */
 		safe_send(rfb->clientfd, &msg_type, sizeof(msg_type));
@@ -1180,16 +1196,14 @@ thunk_rfb_poll(thunk_rfb_t *rfb, thunk_r
 	}
 
 	error = ioctl(rfb->clientfd, FIONREAD, &len);
-	if (error) {
-		//printf("rfb: FIONREAD failed: %s\n", strerror(errno));
-		close(rfb->clientfd);
-		rfb->clientfd = -1;
-		return -1;
-	}
+	if (error)
+		goto discon;
 	if (len == 0)
 		return 0;
 
-	recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
+	len = safe_recv(rfb->clientfd, &ch, sizeof(ch));
+	if (len < 0)
+		goto discon;
 
 	event->message_type = ch;
 	switch (ch) {
@@ -1197,25 +1211,39 @@ thunk_rfb_poll(thunk_rfb_t *rfb, thunk_r
 		msg_len = sizeof(set_pixel_format);
 		break;
 	case THUNK_RFB_SET_ENCODINGS:
-		recv(rfb->clientfd, set_encodings, sizeof(set_encodings),
-		    MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd,
+			set_encodings, sizeof(set_encodings));
+		if (len < 0)
+			goto discon;
 		msg_len = 4 * ntohs(*(uint16_t *)&set_encodings[1]);
 		break;
 	case THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST:
-		recv(rfb->clientfd, framebuffer_update_request,
-			sizeof(framebuffer_update_request), MSG_NOSIGNAL);
-#if 0
+		len = safe_recv(rfb->clientfd,
+			framebuffer_update_request,
+			sizeof(framebuffer_update_request));
+		if (len < 0)
+			goto discon;
+#ifdef RFB_DEBUG
+		fprintf(stdout, "framebuffer update request: ");
+		fprintf(stdout, "[%d, %d] + [%d, %d] %s\n",
+			framebuffer_update_request[1],
+			framebuffer_update_request[2],
+			framebuffer_update_request[3],
+			framebuffer_update_request[4],
+			framebuffer_update_request[0]?"Incrmental":"Complete");
+#endif
+			
 		if (framebuffer_update_request[0] == 0) {
-fprintf(stdout, "complete update request\n");
 			/* complete redraw request -> buffer full */
-			rfb->nupdates = __arraycount(rfb->update);
+			rfb->nupdates = __arraycount(rfb->update) + 1;
 		}
-		thunk_rfb_send_pending(rfb);
-#endif
+//		thunk_rfb_send_pending(rfb);
 		msg_len = 0;
 		break;
 	case THUNK_RFB_KEY_EVENT:
-		recv(rfb->clientfd, key_event, sizeof(key_event), MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd, key_event, sizeof(key_event));
+		if (len < 0)
+			goto discon;
 		event->data.key_event.down_flag = key_event[0];
 		event->data.key_event.keysym =
 		    ntohl(*(uint32_t *)&key_event[3]);
@@ -1227,8 +1255,10 @@ fprintf(stdout, "complete update request
 		msg_len = 0;
 		break;
 	case THUNK_RFB_POINTER_EVENT:
-		recv(rfb->clientfd, pointer_event, sizeof(pointer_event),
-		    MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd,
+			pointer_event, sizeof(pointer_event));
+		if (len < 0)
+			goto discon;
 		event->data.pointer_event.button_mask = pointer_event[0];
 		event->data.pointer_event.absx =
 		    ntohs(*(uint16_t *)&pointer_event[1]);
@@ -1243,23 +1273,35 @@ fprintf(stdout, "complete update request
 		msg_len = 0;
 		break;
 	case THUNK_RFB_CLIENT_CUT_TEXT:
-		recv(rfb->clientfd, client_cut_text, sizeof(client_cut_text),
-		    MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd,
+			client_cut_text, sizeof(client_cut_text));
+		if (len < 0)
+			goto discon;
 		msg_len = ntohl(*(uint32_t *)&client_cut_text[3]);
 		break;
 	default:
 		fprintf(stdout, "rfb: unknown message type %d\n", ch);
-		close(rfb->clientfd);
-		rfb->clientfd = -1;
-		return -1;
+		goto discon;
 	}
 
+	if (len < 0)
+		goto discon;
+
 	/* discard any remaining bytes */
 	while (msg_len-- > 0) {
-		recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
+		len = safe_recv(rfb->clientfd, &ch, sizeof(ch));
+		if (len < 0)
+			goto discon;
 	}
 
 	return 1;
+
+discon:
+	//printf("rfb: safe_recv failed: %s\n", strerror(errno));
+	close(rfb->clientfd);
+	rfb->clientfd = -1;
+
+	return -1;
 }
 
 void

Reply via email to