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