forked from KolibriOS/kolibrios
7fe01d3053
git-svn-id: svn://kolibrios.org@260 a494cfbc-eb01-0410-851d-a64ba20cac60
509 lines
11 KiB
NASM
509 lines
11 KiB
NASM
;
|
|
;
|
|
; VNC Client for kolibrios by hidnplayr
|
|
;
|
|
;
|
|
; WORK IN PROGRESS...
|
|
;
|
|
; FEEL FREE TO CONTRIBUTE !
|
|
;
|
|
; hidnplayr@gmail.com
|
|
;
|
|
|
|
use32
|
|
|
|
org 0x0
|
|
|
|
db 'MENUET00' ; 8 byte id
|
|
dd 38 ; required os
|
|
dd START ; program start
|
|
dd I_END ; program image size
|
|
dd IM_END ; required amount of memory
|
|
dd 0 ; reserved=no extended header
|
|
|
|
__DEBUG__ equ 1
|
|
__DEBUG_LEVEL__ equ 1
|
|
STRLEN = 64
|
|
xpos = 4
|
|
ypos = 22
|
|
|
|
TIMEOUT = 60 ; timeout in seconds
|
|
BUFFER = 512 ; Buffer size for DNS
|
|
|
|
include 'fdo.inc'
|
|
include 'ETH.INC'
|
|
include 'logon.inc'
|
|
include 'raw.inc'
|
|
include 'copyrect.inc'
|
|
|
|
|
|
START: ; start of execution
|
|
call red_logon
|
|
|
|
mov eax,40 ; Report events
|
|
mov ebx,10000000b ; Only Stack
|
|
int 0x40
|
|
|
|
mov eax,67 ; resize the window (hide it)
|
|
xor ebx,ebx
|
|
mov ecx,ebx
|
|
mov edx,ebx
|
|
mov esi,ebx
|
|
int 0x40
|
|
|
|
resolve first,[server_ip] ; the input window putted the server @ 'first', resolve it into a real ip
|
|
mov [server_port],5900 ; no port input for now, only standard port 5900
|
|
|
|
DEBUGF 1,'connecting to %u.%u.%u.%u:%u\n',1[server_ip],1[server_ip+1],1[server_ip+2],1[server_ip+3],4[server_port]
|
|
eth.search_port 1000,edx ; Find a free port starting from 1001 and store in edx
|
|
eth.open_tcp edx,[server_port],[server_ip],1,[socket] ; open socket
|
|
DEBUGF 1,'Socket opened: %u (port %u)\n',[socket],ecx
|
|
|
|
call read_data
|
|
cmp dword[receive_buffer+1],'RFB '
|
|
jne no_rfb
|
|
eth.write_tcp [socket],12,handshake
|
|
DEBUGF 1,'Sending handshake: protocol version\n'
|
|
|
|
call read_data
|
|
mov eax,receive_buffer+1
|
|
mov eax,[eax]
|
|
bswap eax
|
|
cmp eax,0
|
|
je invalid_security
|
|
cmp eax,1
|
|
je no_security
|
|
cmp eax,2
|
|
je vnc_security
|
|
|
|
jmp close
|
|
|
|
vnc_security:
|
|
mov byte[mode],1
|
|
call red_logon
|
|
|
|
no_security:
|
|
eth.write_tcp [socket],1,shared
|
|
DEBUGF 1,'Sending handshake: shared session?\n'
|
|
|
|
eth.wait_for_data [socket],TIMEOUT*10,close
|
|
eth.read_data [socket],framebuffer,[datapointer],IM_END-receive_buffer ; now the server should send init message
|
|
DEBUGF 1,'Serverinit: bpp:%u depth:%u bigendian:%u truecolor:%u\n',1[pixelformat.bpp],1[pixelformat.depth],1[pixelformat.big_endian],1[pixelformat.true_color]
|
|
mov eax,dword[framebuffer]
|
|
bswap eax
|
|
mov dword[screen],eax
|
|
|
|
eth.write_tcp [socket],20,pixel_format32
|
|
DEBUGF 1,'Sending pixel format\n'
|
|
call read_data
|
|
|
|
; eth.write_tcp [socket],8,encodings
|
|
; DEBUGF 1,'Sending encoding info\n'
|
|
; call read_data
|
|
|
|
mov eax,dword[framebuffer.width]
|
|
mov dword[fbur.width],eax
|
|
|
|
mov eax,40 ; report events
|
|
mov ebx,10100111b ; stack, mouse, button, key, redraw
|
|
int 0x40
|
|
|
|
mov eax,67 ; resize the window
|
|
mov ebx,10
|
|
mov ecx,10
|
|
mov edx,dword[framebuffer]
|
|
bswap edx
|
|
movzx esi,dx
|
|
shr edx,16
|
|
add edx,2*xpos
|
|
add esi,ypos+xpos
|
|
int 0x40
|
|
|
|
; mov byte[fbur.inc],0 ; request a framebufferupdate
|
|
; eth.write_tcp [socket],10,fbur
|
|
|
|
mainloop:
|
|
eth.socket_status [socket],eax
|
|
cmp al,TCB_CLOSE_WAIT
|
|
je close
|
|
|
|
mov eax,23 ; wait for event with timeout
|
|
mov ebx,50 ; 0,5 s
|
|
int 0x40
|
|
|
|
cmp eax,1 ; redraw
|
|
je redraw
|
|
cmp eax,2 ; key
|
|
je key
|
|
cmp eax,3 ; button
|
|
je button
|
|
cmp eax,6 ; mouse
|
|
je mouse
|
|
cmp eax,8
|
|
je network
|
|
|
|
; request an FRB update
|
|
jmp mainloop
|
|
|
|
|
|
network:
|
|
call read_data ; Read the data into the buffer
|
|
|
|
mov eax,[datapointer] ; at least 2 bytes should be received
|
|
sub eax,receive_buffer
|
|
cmp eax,1
|
|
jle mainloop
|
|
|
|
DEBUGF 1,'Data received, %u bytes\n',eax
|
|
|
|
cmp byte[receive_buffer],0
|
|
je framebufferupdate
|
|
|
|
cmp byte[receive_buffer],1
|
|
je setcolourmapentries
|
|
|
|
cmp byte[receive_buffer],2
|
|
je bell
|
|
|
|
cmp byte[receive_buffer],3
|
|
je servercuttext
|
|
|
|
jmp mainloop
|
|
|
|
|
|
framebufferupdate:
|
|
DEBUGF 1,'Framebufferupdate!\n'
|
|
mov di,word[receive_buffer+2]
|
|
bswap edi
|
|
shr edi,16
|
|
mov esi,receive_buffer+4
|
|
|
|
rectangle_loop:
|
|
mov edx,[esi]
|
|
bswap edx
|
|
mov ebx,edx
|
|
shr edx,16
|
|
mov [frame.x],dx
|
|
mov [frame.y],bx
|
|
add esi,4
|
|
mov ecx,[esi]
|
|
bswap ecx
|
|
mov eax,ecx
|
|
shr ecx,16
|
|
mov [frame.width],cx
|
|
mov [frame.height],ax
|
|
add esi,4
|
|
mov eax,[esi]
|
|
add esi,4
|
|
|
|
DEBUGF 1,'screen: width=%u height=%u\nframe: width=%u height=%u x=%u y=%u\n',2[screen.width],2[screen.height],2[frame.width],2[frame.height],2[frame.x],2[frame.y]
|
|
|
|
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,16
|
|
je encoding_ZRLE
|
|
|
|
DEBUGF 1,'FRAME: unknown encoding\n'
|
|
jmp mainloop
|
|
|
|
next_rectangle:
|
|
dec di
|
|
pusha
|
|
call drawbuffer
|
|
popa
|
|
cmp di,0
|
|
jg rectangle_loop
|
|
jmp mainloop
|
|
|
|
encoding_RRE:
|
|
DEBUGF 1,'FRAME: RRE\n'
|
|
|
|
jmp next_rectangle
|
|
|
|
encoding_hextile:
|
|
DEBUGF 1,'FRAME: hextile\n'
|
|
|
|
jmp next_rectangle
|
|
|
|
encoding_ZRLE:
|
|
DEBUGF 1,'FRAME: ZRLE\n'
|
|
|
|
jmp next_rectangle
|
|
|
|
|
|
setcolourmapentries:
|
|
|
|
DEBUGF 1,'Server sended an SetColourMapEntries message\n'
|
|
|
|
jmp mainloop
|
|
|
|
|
|
bell:
|
|
mov eax,55
|
|
mov ebx,eax
|
|
mov esi,beep
|
|
int 0x40
|
|
|
|
jmp mainloop
|
|
|
|
|
|
servercuttext:
|
|
|
|
jmp mainloop
|
|
|
|
|
|
key:
|
|
DEBUGF 1,'Sending key event\n'
|
|
|
|
mov eax,2
|
|
int 0x40
|
|
mov byte[keyevent.key+3],ah
|
|
|
|
; eth.write_tcp [socket],8,keyevent
|
|
|
|
cmp ah,13
|
|
jne @f
|
|
|
|
mov byte[fbur.inc],1
|
|
eth.write_tcp [socket],10,fbur
|
|
jmp mainloop
|
|
@@:
|
|
|
|
cmp ah,30
|
|
jne @f
|
|
|
|
mov byte[fbur.inc],12
|
|
eth.write_tcp [socket],10,fbur
|
|
jmp mainloop
|
|
@@:
|
|
|
|
mov byte[fbur.inc],0
|
|
eth.write_tcp [socket],10,fbur
|
|
|
|
jmp mainloop
|
|
|
|
mouse:
|
|
DEBUGF 1,'Sending mouse event\n'
|
|
|
|
mov eax,37
|
|
mov ebx,1
|
|
int 0x40
|
|
|
|
sub eax,xpos*65536+ypos
|
|
bswap eax
|
|
mov word[pointerevent.x],ax
|
|
shr eax,16
|
|
mov word[pointerevent.y],ax
|
|
|
|
mov eax,37
|
|
mov ebx,2
|
|
int 0x40
|
|
|
|
cmp al,2
|
|
jne @f ; in kolibri right click is 2 (decimal), in RFB protocol it is bit 2 (counting from 0)
|
|
mov al,100b
|
|
@@:
|
|
|
|
mov byte[pointerevent.mask],al
|
|
|
|
eth.write_tcp [socket],6,pointerevent
|
|
|
|
jmp mainloop
|
|
|
|
redraw:
|
|
|
|
DEBUGF 1,'Drawing window\n'
|
|
|
|
mov eax,12
|
|
mov ebx,1
|
|
int 0x40
|
|
|
|
mov eax,0 ; draw window
|
|
mov ebx,dword[framebuffer]
|
|
bswap ebx
|
|
movzx ecx,bx
|
|
shr ebx,16
|
|
add ebx,2*xpos
|
|
add ecx,ypos+xpos
|
|
mov edx,0x03ffffff
|
|
mov esi,0x80555599
|
|
mov edi,0x00ffffff
|
|
int 0x40
|
|
|
|
mov eax,4 ; label
|
|
mov ebx,9*65536+8
|
|
mov ecx,0x10ffffff
|
|
mov edx,name
|
|
mov esi,[name_length]
|
|
bswap esi
|
|
int 0x40
|
|
|
|
call drawbuffer
|
|
|
|
mov eax,12
|
|
mov ebx,2
|
|
int 0x40
|
|
|
|
jmp mainloop
|
|
|
|
drawbuffer:
|
|
|
|
mov eax,7
|
|
mov ebx,framebuffer_data
|
|
mov ecx,dword[screen]
|
|
mov edx,xpos*65536+ypos
|
|
int 0x40
|
|
|
|
ret
|
|
|
|
|
|
button: ; button
|
|
mov eax,17 ; get id
|
|
int 0x40
|
|
|
|
close:
|
|
call read_data
|
|
; eth.close_tcp [socket] ; We're done, close the socket ;;; BUG WHEN CLOSING SCOKET !!
|
|
DEBUGF 1,'Socket closed\n'
|
|
|
|
mov eax,-1
|
|
int 0x40
|
|
|
|
no_rfb:
|
|
DEBUGF 1,'This is no vnc server!\n'
|
|
jmp close
|
|
|
|
invalid_security:
|
|
DEBUGF 1,'Security error: %s\n',receive_buffer+5
|
|
jmp close
|
|
|
|
read_data:
|
|
eth.read_data [socket],receive_buffer,[datapointer],IM_END-receive_buffer
|
|
ret
|
|
|
|
; DATA AREA
|
|
|
|
include_debug_strings ; ALWAYS present in data section
|
|
|
|
handshake db 'RFB 003.003',0x0a
|
|
shared db 0
|
|
beep db 0x85,0x25,0x85,0x40,0
|
|
|
|
pixel_format32 db 0 ; setPixelformat
|
|
rb 3 ; padding
|
|
.bpp db 32 ; bits per pixel
|
|
.depth db 32 ; depth
|
|
.big_endian db 0 ; big-endian flag
|
|
.true_color db 1 ; true-colour flag
|
|
.red_max db 0,255 ; red-max
|
|
.green_max db 0,255 ; green-max
|
|
.blue_max db 0,255 ; blue-max
|
|
.red_shif db 0 ; red-shift
|
|
.green_shift db 8 ; green-shift
|
|
.blue_shift db 16 ; blue-shift
|
|
rb 3 ; padding
|
|
|
|
pixel_format16 db 0 ; setPixelformat
|
|
rb 3 ; padding
|
|
.bpp db 16 ; bits per pixel
|
|
.depth db 16 ; depth
|
|
.big_endian db 0 ; big-endian flag
|
|
.true_color db 1 ; true-colour flag
|
|
.red_max db 0,32 ; red-max
|
|
.green_max db 0,32 ; green-max
|
|
.blue_max db 0,64 ; blue-max
|
|
.red_shif db 0 ; red-shift
|
|
.green_shift db 5 ; green-shift
|
|
.blue_shift db 10 ; blue-shift
|
|
rb 3 ; padding
|
|
|
|
pixel_format8 db 0 ; setPixelformat
|
|
rb 3 ; padding
|
|
.bpp db 8 ; bits per pixel
|
|
.depth db 8 ; depth
|
|
.big_endian db 0 ; big-endian flag
|
|
.true_color db 1 ; true-colour flag
|
|
.red_max db 0,7 ; red-max
|
|
.green_max db 0,7 ; green-max
|
|
.blue_max db 0,3 ; blue-max
|
|
.red_shif db 0 ; red-shift
|
|
.green_shift db 3 ; green-shift
|
|
.blue_shift db 6 ; blue-shift
|
|
rb 3 ; padding
|
|
|
|
encodings db 2 ; setEncodings
|
|
rb 1 ; padding
|
|
db 1,0 ; number of encodings
|
|
db 0,0,0,0 ; raw encoding (DWORD, Big endian order)
|
|
db 1,0,0,0 ; Copyrect encoding
|
|
|
|
fbur db 3 ; frame buffer update request
|
|
.inc db 0 ; incremental
|
|
.x dw 0
|
|
.y dw 0
|
|
.width dw 0
|
|
.height dw 0
|
|
|
|
keyevent db 4 ; keyevent
|
|
.down db 0 ; down-flag
|
|
dw 0 ; padding
|
|
.key dd 0 ; key
|
|
|
|
pointerevent db 5 ; pointerevent
|
|
.mask db 0 ; button-mask
|
|
.x dw 0 ; x-position
|
|
.y dw 0 ; y-position
|
|
|
|
I_END:
|
|
|
|
framebuffer:
|
|
.width dw ?
|
|
.height dw ?
|
|
pixelformat:
|
|
.bpp db ?
|
|
.depth db ?
|
|
.big_endian db ?
|
|
.true_color db ?
|
|
.red_max dw ?
|
|
.green_max dw ?
|
|
.blue_max dw ?
|
|
.red_shift db ?
|
|
.green_shift db ?
|
|
.blue_shift db ?
|
|
.padding rb 3
|
|
name_length dd ?
|
|
name rb 256
|
|
|
|
server_ip dd 0
|
|
server_port dd 0
|
|
socket dd 0
|
|
datapointer dd 0
|
|
|
|
frame:
|
|
.width dw 0
|
|
.height dw 0
|
|
.x dw 0
|
|
.y dw 0
|
|
|
|
screen:
|
|
.height dw 0
|
|
.width dw 0
|
|
|
|
dnsMsg:
|
|
receive_buffer rb 5*1024*1024 ; 5 mb buffer for received data (incoming frbupdate etc)
|
|
framebuffer_data rb 1024*768*3 ; framebuffer
|
|
|
|
IM_END:
|
|
|
|
|