;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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: mcall 40, 0 ; disable all events for this thread ; resolve name push esp ; reserve stack place invoke getaddrinfo, serveraddr, 0, 0, esp pop esi ; test for error test eax, eax jnz err_dns 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 invoke freeaddrinfo, esi mcall socket, AF_INET4, SOCK_STREAM, 0 cmp eax, -1 je err_sock mov [socketnum], eax mcall connect, [socketnum], sockaddr1, 18 cmp eax, -1 je err_connect ; TODO: implement timeout call wait_for_data cmp dword[receive_buffer], "RFB " jne err_proto 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], 0x01000000 je no_security cmp dword[receive_buffer], 0x02000000 je vnc_security jmp err_security vnc_security: mov [status], STATUS_LOGIN call draw_gui 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[FramebufferUpdateRequest.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], SetPixelFormat8, 20, 0 DEBUGF 1, "Sending pixel format\n" mcall send, [socketnum], SetEncodings, 12, 0 DEBUGF 1, "Sending encoding info\n" ; Set main window caption to servername mov ecx, dword[receive_buffer+framebuffer.name_length] bswap ecx cmp ecx, 64 jbe @f mov ecx, 64 @@: lea esi, [receive_buffer+framebuffer.name] mov edi, servername rep movsb mov byte[edi], 0 mov [name.dash], "-" ; Tell the main thread we are ready for business! mov [status], STATUS_CONNECTED ; Request initial update mov [FramebufferUpdateRequest.inc], 0 request_fbu: DEBUGF 1, "Requesting framebuffer update\n" mcall send, [socketnum], FramebufferUpdateRequest, 10, 0 mov [FramebufferUpdateRequest.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 2, "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 @@: xor eax, eax lodsw xchg al, ah mov [rectangle.x], eax lodsw xchg al, ah mov [rectangle.y], eax lodsw xchg al, ah mov [rectangle.width], eax lodsw xchg al, ah mov [rectangle.height], eax 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 2, "unknown encoding: %u\n", eax jmp thread_loop next_rectangle: inc [update_framebuffer] 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 err_disconnected add [datapointer], eax ; Check for buffer overflow cmp [datapointer], receive_buffer + RECEIVE_BUFFER_SIZE jbe @f ; Buffer is full, first needed data by program is pointed to by esi. ; Move all remaining data, starting from esi, to begin of buffer cmp esi, receive_buffer je err_proto mov ecx, [datapointer] sub ecx, esi mov edi, receive_buffer rep movsb mov [datapointer], edi mov esi, receive_buffer @@: cmp eax, 4096 je .more ret wait_for_data: ; FIXME: add timeout mcall recv, [socketnum], receive_buffer, 4096, 0 cmp eax, -1 je err_disconnected test eax, eax jz wait_for_data ret err_disconnected: mov [status], STATUS_DISCONNECTED inc [update_gui] mcall -1 err_dns: mov [status], STATUS_DNS_ERR inc [update_gui] mcall -1 err_sock: mov [status], STATUS_SOCK_ERR inc [update_gui] mcall -1 err_connect: mov [status], STATUS_CONNECT_ERR inc [update_gui] mcall -1 ret err_proto: mov [status], STATUS_PROTO_ERR inc [update_gui] mcall -1 ret err_security: mov [status], STATUS_SECURITY_ERR inc [update_gui] mcall -1 ret