panic("%s: cannot accept a connection if not listening!", name());
int fd = listener.accept(true);
- fatal_if(fd < 0, "%s: failed to accept VNC connection!", name());
+ if (fd < 0) {
+ warn("%s: failed to accept VNC connection!", name());
+ return;
+ }
if (dataFd != -1) {
char message[] = "vnc server already attached!\n";
dataFd = fd;
// Send our version number to the client
- write((uint8_t*)vncVersion(), strlen(vncVersion()));
+ write((uint8_t *)vncVersion(), strlen(vncVersion()));
// read the client response
dataEvent = new DataEvent(this, dataFd, POLLIN);
VncServer::data()
{
// We have new data, see if we can handle it
- size_t len;
DPRINTF(VNC, "Vnc client message recieved\n");
switch (curState) {
case WaitForClientInit:
// Don't care about shared, just need to read it out of the socket
uint8_t shared;
- len = read(&shared);
- assert(len == 1);
+ if (!read(&shared))
+ return;
// Send our idea of the frame buffer
sendServerInit();
break;
case NormalPhase:
uint8_t message_type;
- len = read(&message_type);
- if (!len) {
- detach();
+ if (!read(&message_type))
return;
- }
- assert(len == 1);
switch (message_type) {
case ClientSetPixelFormat:
recvCutText();
break;
default:
- panic("Unimplemented message type recv from client: %d\n",
- message_type);
+ warn("Unimplemented message type recv from client: %d\n",
+ message_type);
+ detach();
break;
}
break;
// read from socket
-size_t
+bool
VncServer::read(uint8_t *buf, size_t len)
{
if (dataFd < 0)
} while (ret == -1 && errno == EINTR);
- if (ret <= 0){
- DPRINTF(VNC, "Read failed.\n");
+ if (ret != len) {
+ DPRINTF(VNC, "Read failed %d.\n", ret);
detach();
- return 0;
+ return false;
}
- return ret;
+ return true;
}
-size_t
+bool
VncServer::read1(uint8_t *buf, size_t len)
{
- size_t read_len M5_VAR_USED;
- read_len = read(buf + 1, len - 1);
- assert(read_len == len - 1);
- return read_len;
+ return read(buf + 1, len - 1);
}
template<typename T>
-size_t
+bool
VncServer::read(T* val)
{
- return read((uint8_t*)val, sizeof(T));
+ return read((uint8_t *)val, sizeof(T));
}
// write to socket
-size_t
+bool
VncServer::write(const uint8_t *buf, size_t len)
{
if (dataFd < 0)
panic("Vnc client not properly attached.\n");
- ssize_t ret;
- ret = atomic_write(dataFd, buf, len);
+ ssize_t ret = atomic_write(dataFd, buf, len);
- if (ret < len)
+ if (ret != len) {
+ DPRINTF(VNC, "Write failed.\n");
detach();
+ return false;
+ }
- return ret;
+ return true;
}
template<typename T>
-size_t
+bool
VncServer::write(T* val)
{
- return write((uint8_t*)val, sizeof(T));
+ return write((uint8_t *)val, sizeof(T));
}
-size_t
+bool
VncServer::write(const char* str)
{
- return write((uint8_t*)str, strlen(str));
+ return write((uint8_t *)str, strlen(str));
}
// detach a vnc client
VncServer::sendError(const char* error_msg)
{
uint32_t len = strlen(error_msg);
- write(&len);
+ if (!write(&len))
+ return;
write(error_msg);
}
// Null terminate the message so it's easier to work with
version_string[12] = 0;
- len = read((uint8_t*)version_string, 12);
- assert(len == 12);
+ if (!read((uint8_t *)version_string, sizeof(version_string) - 1)) {
+ warn("Failed to read protocol version.");
+ return;
+ }
uint32_t major, minor;
warn(" Malformed protocol version %s\n", version_string);
sendError("Malformed protocol version\n");
detach();
+ return;
}
DPRINTF(VNC, "Client request protocol version %d.%d\n", major, minor);
uint8_t err = AuthInvalid;
write(&err);
detach();
+ return;
}
// Auth is different based on version number
if (minor < 7) {
uint32_t sec_type = htobe((uint32_t)AuthNone);
- write(&sec_type);
+ if (!write(&sec_type))
+ return;
} else {
uint8_t sec_cnt = 1;
uint8_t sec_type = htobe((uint8_t)AuthNone);
- write(&sec_cnt);
- write(&sec_type);
+ if (!write(&sec_cnt) || !write(&sec_type))
+ return;
}
// Wait for client to respond
assert(curState == WaitForSecurityResponse);
uint8_t security_type;
- size_t len M5_VAR_USED = read(&security_type);
-
- assert(len == 1);
+ if (!read(&security_type))
+ return;
if (security_type != AuthNone) {
warn("Unknown VNC security type\n");
DPRINTF(VNC, "Sending security auth OK\n");
uint32_t success = htobe(VncOK);
- write(&success);
+ if (!write(&success))
+ return;
curState = WaitForClientInit;
}
msg.namelen = htobe(msg.namelen);
memcpy(msg.name, "M5", 2);
- write(&msg);
+ if (!write(&msg))
+ return;
curState = NormalPhase;
}
DPRINTF(VNC, "Received pixel format from client message\n");
PixelFormatMessage pfm;
- read1((uint8_t*)&pfm, sizeof(PixelFormatMessage));
+ if (!read1((uint8_t *)&pfm, sizeof(PixelFormatMessage)))
+ return;
DPRINTF(VNC, " -- bpp = %d; depth = %d; be = %d\n", pfm.px.bpp,
pfm.px.depth, pfm.px.bigendian);
betoh(pfm.px.bluemax) != pixelFormat.bluemax ||
betoh(pfm.px.redshift) != pixelFormat.redshift ||
betoh(pfm.px.greenshift) != pixelFormat.greenshift ||
- betoh(pfm.px.blueshift) != pixelFormat.blueshift)
- fatal("VNC client doesn't support true color raw encoding\n");
+ betoh(pfm.px.blueshift) != pixelFormat.blueshift) {
+ warn("VNC client doesn't support true color raw encoding\n");
+ detach();
+ }
}
void
DPRINTF(VNC, "Received supported encodings from client\n");
PixelEncodingsMessage pem;
- read1((uint8_t*)&pem, sizeof(PixelEncodingsMessage));
+ if (!read1((uint8_t *)&pem, sizeof(PixelEncodingsMessage)))
+ return;
pem.num_encodings = betoh(pem.num_encodings);
for (int x = 0; x < pem.num_encodings; x++) {
int32_t encoding;
- size_t len M5_VAR_USED;
- len = read(&encoding);
- assert(len == sizeof(encoding));
+ if (!read(&encoding))
+ return;
DPRINTF(VNC, " -- supports %d\n", betoh(encoding));
switch (betoh(encoding)) {
}
}
- if (!supportsRawEnc)
- fatal("VNC clients must always support raw encoding\n");
+ if (!supportsRawEnc) {
+ warn("VNC clients must always support raw encoding\n");
+ detach();
+ }
}
void
DPRINTF(VNC, "Received frame buffer update request from client\n");
FrameBufferUpdateReq fbr;
- read1((uint8_t*)&fbr, sizeof(FrameBufferUpdateReq));
+ if (!read1((uint8_t *)&fbr, sizeof(FrameBufferUpdateReq)))
+ return;
fbr.x = betoh(fbr.x);
fbr.y = betoh(fbr.y);
{
DPRINTF(VNC, "Received keyboard input from client\n");
KeyEventMessage kem;
- read1((uint8_t*)&kem, sizeof(KeyEventMessage));
+ if (!read1((uint8_t *)&kem, sizeof(KeyEventMessage)))
+ return;
kem.key = betoh(kem.key);
DPRINTF(VNC, " -- received key code %d (%s)\n", kem.key, kem.down_flag ?
DPRINTF(VNC, "Received pointer input from client\n");
PointerEventMessage pem;
- read1((uint8_t*)&pem, sizeof(PointerEventMessage));;
+ if (!read1((uint8_t *)&pem, sizeof(PointerEventMessage)))
+ return;
pem.x = betoh(pem.x);
pem.y = betoh(pem.y);
DPRINTF(VNC, "Received client copy buffer message\n");
ClientCutTextMessage cct;
- read1((uint8_t*)&cct, sizeof(ClientCutTextMessage));
+ if (!read1((uint8_t *)&cct, sizeof(ClientCutTextMessage)))
+ return;
char str[1025];
size_t data_len = betoh(cct.length);
DPRINTF(VNC, "String length %d\n", data_len);
while (data_len > 0) {
- size_t len;
size_t bytes_to_read = data_len > 1024 ? 1024 : data_len;
- len = read((uint8_t*)&str, bytes_to_read);
+ if (!read((uint8_t *)&str, bytes_to_read))
+ return;
str[bytes_to_read] = 0;
- assert(len >= data_len);
- data_len -= len;
+ data_len -= bytes_to_read;
DPRINTF(VNC, "Buffer: %s\n", str);
}
fbr.encoding = htobe(fbr.encoding);
// send headers to client
- write(&fbu);
- write(&fbr);
+ if (!write(&fbu) || !write(&fbr))
+ return;
assert(fb);
raw_pixel += pixelConverter.length;
}
- write(line_buffer.data(), line_buffer.size());
+ if (!write(line_buffer.data(), line_buffer.size()))
+ return;
}
}
fbr.encoding = htobe(fbr.encoding);
// send headers to client
- write(&fbu);
+ if (!write(&fbu))
+ return;
write(&fbr);
// No actual data is sent in this message
/** Read some data from the client
* @param buf the data to read
* @param len the amount of data to read
- * @return length read
+ * @return whether the read was successful
*/
- size_t read(uint8_t *buf, size_t len);
+ bool read(uint8_t *buf, size_t len);
/** Read len -1 bytes from the client into the buffer provided + 1
* assert that we read enough bytes. This function exists to handle
* the first byte which describes which one we're reading
* @param buf the address of the buffer to add one to and read data into
* @param len the amount of data + 1 to read
- * @return length read
+ * @return whether the read was successful.
*/
- size_t read1(uint8_t *buf, size_t len);
+ bool read1(uint8_t *buf, size_t len);
/** Templated version of the read function above to
* read simple data to the client
* @param val data to recv from the client
*/
- template <typename T> size_t read(T* val);
+ template <typename T> bool read(T* val);
/** Write a buffer to the client.
* @param buf buffer to send
* @param len length of the buffer
- * @return number of bytes sent
+ * @return whether the write was successful
*/
- size_t write(const uint8_t *buf, size_t len);
+ bool write(const uint8_t *buf, size_t len);
/** Templated version of the write function above to
* write simple data to the client
* @param val data to send to the client
*/
- template <typename T> size_t write(T* val);
+ template <typename T> bool write(T* val);
/** Send a string to the client
* @param str string to transmit
*/
- size_t write(const char* str);
+ bool write(const char* str);
/** Check the client's protocol verion for compatibility and send
* the security types we support