static FAR void *vnc_updater(FAR void *arg) { FAR struct vnc_session_s *session = (FAR struct vnc_session_s *)arg; FAR struct vnc_fbupdate_s *srcrect; int ret; DEBUGASSERT(session != NULL); gvdbg("Updater running for Display %d\n", session->display); /* Loop, processing updates until we are asked to stop. * REVISIT: Probably need some kind of signal mechanism to wake up * vnc_remove_queue() in order to stop. Or perhaps a special STOP * message in the queue? */ while (session->state == VNCSERVER_RUNNING) { /* Get the next queued rectangle update. This call will block until an * upate is available for the case where the update queue is empty. */ srcrect = vnc_remove_queue(session); DEBUGASSERT(srcrect != NULL); updvdbg("Dequeued {(%d, %d),(%d, %d)}\n", srcrect->rect.pt1.x, srcrect->rect.pt1.y, srcrect->rect.pt2.x, srcrect->rect.pt2.y); /* Attempt to use RRE encoding */ ret = vnc_rre(session, &srcrect->rect); if (ret == 0) { /* Perform the framebuffer update using the default RAW encoding */ ret = vnc_raw(session, &srcrect->rect); } /* Release the update structure */ vnc_free_update(session, srcrect); /* Break out and terminate the server if the encoding failed */ if (ret < 0) { gdbg("ERROR: Encoding failed: %d\n", ret); break; } } session->state = VNCSERVER_STOPPED; return NULL; }
static int vnc_inflate(struct connection *cx) { struct zlib *zlib = cx->encoding_def[zlib_encoding].priv; int length; int res; int flush; const uint32_t max_length = 0x100000; int chunked; struct buffer input; debug(3, "zlib_inflate\n"); chunked = zlib->length > max_length; length = chunked ? max_length : zlib->length; if (cx->input.wpos < cx->input.rpos + length) { length = cx->input.wpos - cx->input.rpos; chunked = 0; flush = Z_NO_FLUSH; } else flush = chunked ? Z_NO_FLUSH : Z_SYNC_FLUSH; zlib->zstr.avail_in = length; zlib->zstr.next_in = &cx->input.data[cx->input.rpos]; do { if (cx->work.wpos == cx->work.size) { if (buffer_reserve(&cx->work, cx->work.size + 65536)) { debug(1, "zlib realloc failed\n"); return close_connection(cx, -1); } } zlib->zstr.avail_out = cx->work.size - cx->work.wpos; zlib->zstr.next_out = &cx->work.data[cx->work.wpos]; res = inflate(&zlib->zstr, flush); switch (res) { case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: debug(1, "zlib inflate error %d\n", res); inflateEnd(&zlib->zstr); return close_connection(cx, -1); } cx->work.wpos = cx->work.size - zlib->zstr.avail_out; } while (!zlib->zstr.avail_out); zlib->length -= length - zlib->zstr.avail_in; cx->input.rpos += length - zlib->zstr.avail_in; if (zlib->length) { cx->action = vnc_inflate; return chunked; } input = cx->input; cx->input = cx->work; res = vnc_raw(cx); cx->input = input; if (!res) return close_connection(cx, -1); cx->work.rpos = 0; cx->work.wpos = 0; return 1; }