;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2010-2015. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;; VNC client for KolibriOS ;; ;; ;; ;; Written by hidnplayr@kolibrios.org ;; ;; ;; ;; GNU GENERAL PUBLIC LICENSE ;; ;; Version 2, June 1991 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; thread_start: DEBUGF 1, "I am the thread!\n" mcall 40, 0 ; disable all events ; resolve name push esp ; reserve stack place invoke getaddrinfo, serveraddr, 0, 0, esp pop esi ; test for error test eax, eax jnz exit mov eax, [esi+addrinfo.ai_addr] mov eax, [eax+sockaddr_in.sin_addr] mov [sockaddr1.ip], eax DEBUGF 1, "Connecting to %u.%u.%u.%u:%u\n", \ [sockaddr1.ip]:1, [sockaddr1.ip+1]:1, \ [sockaddr1.ip+2]:1, [sockaddr1.ip+3]:1, \ [sockaddr1.port]:2 mcall socket, AF_INET4, SOCK_STREAM, 0 test eax, eax jz exit ;;; invoke freeaddrinfo, ?? mov [socketnum], eax mcall connect, [socketnum], sockaddr1, 18 ;;; test eax, eax ; TODO: implement timeout call wait_for_data cmp dword[receive_buffer], "RFB " jne no_rfb DEBUGF 1, "received: %s\n", receive_buffer mcall send, [socketnum], handshake, 12, 0 DEBUGF 1, "Sending handshake: protocol version\n" call wait_for_data cmp dword[receive_buffer], 0x00000000 je invalid_security cmp dword[receive_buffer], 0x01000000 je no_security cmp dword[receive_buffer], 0x02000000 je vnc_security DEBUGF 1, "Unknown security type\n" jmp exit vnc_security: mov byte[mode], 1 call logon no_security: mcall send, [socketnum], ClientInit, 1, 0 DEBUGF 1, "ClientInit sent\n" call wait_for_data ; now the server should send init message DEBUGF 1, "Serverinit: bpp: %u depth: %u bigendian: %u truecolor: %u\n", \ [receive_buffer+framebuffer.pixelformat.bpp]:1, \ [receive_buffer+framebuffer.pixelformat.depth]:1, \ [receive_buffer+framebuffer.pixelformat.big_endian]:1, \ [receive_buffer+framebuffer.pixelformat.true_color]:1 mov eax, dword[receive_buffer+framebuffer.width] mov dword[fbur.width], eax bswap eax mov dword[screen], eax DEBUGF 1, "Screen width=%u, height=%u\n", [screen.width]:2, [screen.height]:2 mcall send, [socketnum], pixel_format8, 20, 0 DEBUGF 1, "Sending pixel format\n" mcall send, [socketnum], encodings, 12, 0 DEBUGF 1, "Sending encoding info\n" mov [thread_ready], 1 ; Request initial update mov [fbur.inc], 0 request_fbu: DEBUGF 1, "Requesting framebuffer update\n" mcall send, [socketnum], fbur, 10, 0 mov [fbur.inc], 1 thread_loop: call read_data ; Read the data into the buffer lodsb cmp al, 0 je framebufferupdate cmp al, 1 je setcolourmapentries cmp al, 2 je bell cmp al, 3 je servercuttext DEBUGF 1, "Unknown server command: %u\n", al jmp thread_loop framebufferupdate: @@: lea eax, [esi+6] cmp [datapointer], eax jae @f call read_data.more jmp @b @@: inc esi ; padding lodsw xchg al, ah mov [rectangles], ax DEBUGF 1, "Framebufferupdate: %u rectangles\n", ax rectangle_loop: @@: lea eax, [esi+12] cmp [datapointer], eax jae @f call read_data.more jmp @b @@: lodsd ; position bswap eax mov [rectangle.y], ax shr eax, 16 mov [rectangle.x], ax lodsd ; size bswap eax mov [rectangle.height], ax shr eax, 16 mov [rectangle.width], ax lodsd ; encoding DEBUGF 1, "rectangle: width=%u height=%u x=%u y=%u encoding: ",\ [rectangle.width]:2, [rectangle.height]:2, [rectangle.x]:2, [rectangle.y]:2 cmp eax, 0 je encoding_raw cmp eax, 1 je encoding_copyrect ; cmp eax, 2 ; je encoding_RRE ; cmp eax, 5 ; je encoding_hextile ; cmp eax, 15 ; je encoding_TRLE ; cmp eax, 16 ; je encoding_ZRLE DEBUGF 1, "\nunknown encoding: %u\n", eax jmp thread_loop ;; jmp rectangle_loop next_rectangle: push esi call drawbuffer pop esi dec [rectangles] jnz rectangle_loop jmp request_fbu setcolourmapentries: DEBUGF 1, "Server sent SetColourMapEntries message\n" ; TODO jmp thread_loop bell: mcall 55, 55, , , beep jmp thread_loop servercuttext: DEBUGF 1, "Server cut text\n" @@: lea eax, [esi+7] cmp [datapointer], eax jae @f call read_data.more jmp @b @@: add esi, 3 lodsd bswap eax mov ecx, eax @@: lea eax, [esi+ecx] cmp [datapointer], eax jae @f call read_data.more jmp @b @@: ; TODO: paste text to clipboard DEBUGF 1, "%u bytes of text\n", ecx add esi, ecx jmp thread_loop read_data: mov [datapointer], receive_buffer mov esi, receive_buffer .more: push ebx ecx edx esi edi mcall recv, [socketnum], [datapointer], 4096, 0 pop edi esi edx ecx ebx cmp eax, -1 je .error add [datapointer], eax ; TODO: check for buffer overflow cmp eax, 4096 je .more ret .error: DEBUGF 1, "Socket error!\n" mcall -1 ret wait_for_data: ; FIXME: add timeout mcall recv, [socketnum], receive_buffer, 4096, 0 cmp eax, -1 je .error test eax, eax jz wait_for_data ret .error: DEBUGF 1, "Socket error!\n" mcall -1 ret