Subversion Repositories Kolibri OS

Rev

Rev 5677 | Rev 5708 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5663 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2010-2015. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  VNC client for KolibriOS                                       ;;
7
;;                                                                 ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
9
;;                                                                 ;;
10
;;          GNU GENERAL PUBLIC LICENSE                             ;;
11
;;             Version 2, June 1991                                ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3545 hidnplayr 14
 
15
thread_start:
16
 
5668 hidnplayr 17
        mcall   40, 0                   ; disable all events for this thread
3545 hidnplayr 18
 
19
; resolve name
5668 hidnplayr 20
        push    esp                     ; reserve stack place
5663 hidnplayr 21
        invoke  getaddrinfo, serveraddr, 0, 0, esp
3545 hidnplayr 22
        pop     esi
23
; test for error
24
        test    eax, eax
5668 hidnplayr 25
        jnz     err_dns
3545 hidnplayr 26
 
27
        mov     eax, [esi+addrinfo.ai_addr]
28
        mov     eax, [eax+sockaddr_in.sin_addr]
29
        mov     [sockaddr1.ip], eax
30
 
5663 hidnplayr 31
        DEBUGF  1, "Connecting to %u.%u.%u.%u:%u\n", \
5680 hidnplayr 32
        [sockaddr1.ip]:1, [sockaddr1.ip+1]:1, [sockaddr1.ip+2]:1, [sockaddr1.ip+3]:1, \
33
        [sockaddr1.port]:2
3545 hidnplayr 34
 
5668 hidnplayr 35
        invoke  freeaddrinfo, esi
36
 
3545 hidnplayr 37
        mcall   socket, AF_INET4, SOCK_STREAM, 0
5668 hidnplayr 38
        cmp     eax, -1
39
        je      err_sock
40
 
3545 hidnplayr 41
        mov     [socketnum], eax
42
        mcall   connect, [socketnum], sockaddr1, 18
5668 hidnplayr 43
        cmp     eax, -1
44
        je      err_connect
3545 hidnplayr 45
 
5663 hidnplayr 46
        ; TODO: implement timeout
3545 hidnplayr 47
        call    wait_for_data
48
 
5663 hidnplayr 49
        cmp     dword[receive_buffer], "RFB "
5668 hidnplayr 50
        jne     err_proto
5680 hidnplayr 51
        DEBUGF  1, "Sending handshake\n"
5668 hidnplayr 52
        mcall   send, [socketnum], HandShake, 12, 0
3545 hidnplayr 53
        call    wait_for_data
54
 
5680 hidnplayr 55
        cmp     dword[receive_buffer], 0x01000000       ; no security
56
        je      initialize
57
        cmp     dword[receive_buffer], 0x02000000       ; VNC security
3545 hidnplayr 58
        je      vnc_security
5680 hidnplayr 59
 
5668 hidnplayr 60
        jmp     err_security
3545 hidnplayr 61
 
62
vnc_security:
63
 
5680 hidnplayr 64
        mov     dword[password], 0
65
        mov     dword[password+4], 0
66
 
67
        and     [USERbox.flags], not ed_focus
68
        or      [USERbox.flags], ed_disabled
69
        or      [PASSbox.flags], ed_focus
70
 
71
        mov     [status], STATUS_REQ_LOGIN
72
        inc     [update_gui]
73
  @@:
74
        mcall   5, 10
75
        cmp     [status], STATUS_LOGIN
76
        je      @f
77
        cmp     [status], STATUS_REQ_LOGIN
78
        je      @r
79
        mcall   -1
80
  @@:
81
        DEBUGF  1, "VNC authentication\n"
82
 
83
; Bit reverse the password and create DES keys
84
 
85
        mov     ebx, dword[password]
86
        mov     edx, ebx
87
        and     ebx, 0xf0f0f0f0
88
        shr     ebx, 4
89
        and     edx, 0x0f0f0f0f
90
        shl     edx, 4
91
        or      ebx, edx
92
        mov     edx, ebx
93
        and     ebx, 0xCCCCCCCC
94
        shr     ebx, 2
95
        and     edx, 0x33333333
96
        shl     edx, 2
97
        or      ebx, edx
98
        mov     edx, ebx
99
        and     ebx, 0xAAAAAAAA
100
        shr     ebx, 1
101
        and     edx, 0x55555555
102
        shl     edx, 1
103
        or      ebx, edx
104
        bswap   ebx
105
 
106
        mov     eax, dword[password+4]
107
        mov     edx, eax
108
        and     eax, 0xf0f0f0f0
109
        shr     eax, 4
110
        and     edx, 0x0f0f0f0f
111
        shl     edx, 4
112
        or      eax, edx
113
        mov     edx, eax
114
        and     eax, 0xCCCCCCCC
115
        shr     eax, 2
116
        and     edx, 0x33333333
117
        shl     edx, 2
118
        or      eax, edx
119
        mov     edx, eax
120
        and     eax, 0xAAAAAAAA
121
        shr     eax, 1
122
        and     edx, 0x55555555
123
        shl     edx, 1
124
        or      edx, eax
125
        bswap   edx
126
 
127
        mov     edi, keys
128
        call    DES_create_keys
129
 
130
; Encrypt message with DES
131
 
132
        mov     ebx, dword[receive_buffer+4]
133
        mov     edx, dword[receive_buffer+8]
134
        call    encrypt_DES
135
        mov     dword[receive_buffer+4], ebx
136
        mov     dword[receive_buffer+8], edx
137
 
138
        mov     ebx, dword[receive_buffer+12]
139
        mov     edx, dword[receive_buffer+16]
140
        call    encrypt_DES
141
        mov     dword[receive_buffer+12], ebx
142
        mov     dword[receive_buffer+16], edx
143
 
144
; Blank out the password and key fields in RAM
145
 
146
        mov     edi, password
147
        mov     ecx, 384/4
148
        xor     eax, eax
149
        rep     stosd
150
 
151
; Send the authentication response to server
152
 
153
        mcall   send, [socketnum], receive_buffer+4, 16, 0
154
 
155
        call    wait_for_data
156
        cmp     dword[receive_buffer], 0
157
        jne     err_login
158
;        jmp     initialize
159
 
160
initialize:
161
        DEBUGF  1, "Sending ClientInit\n"
5663 hidnplayr 162
        mcall   send, [socketnum], ClientInit, 1, 0
3545 hidnplayr 163
 
164
        call    wait_for_data       ; now the server should send init message
165
 
5663 hidnplayr 166
        DEBUGF  1, "Serverinit: bpp: %u depth: %u bigendian: %u truecolor: %u\n", \
167
        [receive_buffer+framebuffer.pixelformat.bpp]:1, \
168
        [receive_buffer+framebuffer.pixelformat.depth]:1, \
169
        [receive_buffer+framebuffer.pixelformat.big_endian]:1, \
170
        [receive_buffer+framebuffer.pixelformat.true_color]:1
3545 hidnplayr 171
 
5663 hidnplayr 172
        mov     eax, dword[receive_buffer+framebuffer.width]
5668 hidnplayr 173
        mov     dword[FramebufferUpdateRequest.width], eax
3545 hidnplayr 174
        bswap   eax
5663 hidnplayr 175
        mov     dword[screen], eax
176
        DEBUGF  1, "Screen width=%u, height=%u\n", [screen.width]:2, [screen.height]:2
3545 hidnplayr 177
 
5677 hidnplayr 178
        DEBUGF  1, "Sending pixel format\n"
179
if BITS_PER_PIXEL = 8
5668 hidnplayr 180
        mcall   send, [socketnum], SetPixelFormat8, 20, 0
5677 hidnplayr 181
else if BITS_PER_PIXEL = 16
182
        mcall   send, [socketnum], SetPixelFormat16, 20, 0
183
else
184
        mcall   send, [socketnum], SetPixelFormat24, 20, 0
185
end if
3545 hidnplayr 186
 
5677 hidnplayr 187
        DEBUGF  1, "Sending encoding info\n"
5668 hidnplayr 188
        mcall   send, [socketnum], SetEncodings, 12, 0
3545 hidnplayr 189
 
5668 hidnplayr 190
; Set main window caption to servername
191
        mov     ecx, dword[receive_buffer+framebuffer.name_length]
192
        bswap   ecx
193
        cmp     ecx, 64
194
        jbe     @f
195
        mov     ecx, 64
196
  @@:
197
        lea     esi, [receive_buffer+framebuffer.name]
198
        mov     edi, servername
199
        rep movsb
200
        mov     byte[edi], 0
201
        mov     [name.dash], "-"
3545 hidnplayr 202
 
5668 hidnplayr 203
; Tell the main thread we are ready for business!
204
        mov     [status], STATUS_CONNECTED
205
 
5663 hidnplayr 206
; Request initial update
5668 hidnplayr 207
        mov     [FramebufferUpdateRequest.inc], 0
5663 hidnplayr 208
 
209
request_fbu:
210
        DEBUGF  1, "Requesting framebuffer update\n"
5668 hidnplayr 211
        mcall   send, [socketnum], FramebufferUpdateRequest, 10, 0
212
        mov     [FramebufferUpdateRequest.inc], 1
3545 hidnplayr 213
 
214
thread_loop:
215
        call    read_data              ; Read the data into the buffer
216
 
5663 hidnplayr 217
        lodsb
218
        cmp     al, 0
3545 hidnplayr 219
        je      framebufferupdate
5663 hidnplayr 220
        cmp     al, 1
3545 hidnplayr 221
        je      setcolourmapentries
5663 hidnplayr 222
        cmp     al, 2
3545 hidnplayr 223
        je      bell
5663 hidnplayr 224
        cmp     al, 3
3545 hidnplayr 225
        je      servercuttext
226
 
5670 hidnplayr 227
        DEBUGF  2, "Unknown server command: %u\n", al
3545 hidnplayr 228
        jmp     thread_loop
229
 
230
framebufferupdate:
231
 
5663 hidnplayr 232
  @@:
233
        lea     eax, [esi+6]
234
        cmp     [datapointer], eax
235
        jae     @f
236
        call    read_data.more
237
        jmp     @b
238
  @@:
239
 
240
        inc     esi     ; padding
241
        lodsw
3545 hidnplayr 242
        xchg    al, ah
5663 hidnplayr 243
        mov     [rectangles], ax
244
        DEBUGF  1, "Framebufferupdate: %u rectangles\n", ax
3545 hidnplayr 245
 
5663 hidnplayr 246
rectangle_loop:
3545 hidnplayr 247
 
5663 hidnplayr 248
  @@:
249
        lea     eax, [esi+12]
250
        cmp     [datapointer], eax
251
        jae     @f
252
        call    read_data.more
253
        jmp     @b
254
  @@:
3545 hidnplayr 255
 
5668 hidnplayr 256
        xor     eax, eax
257
        lodsw
258
        xchg    al, ah
259
        mov     [rectangle.x], eax
260
        lodsw
261
        xchg    al, ah
262
        mov     [rectangle.y], eax
263
        lodsw
264
        xchg    al, ah
265
        mov     [rectangle.width], eax
266
        lodsw
267
        xchg    al, ah
268
        mov     [rectangle.height], eax
3545 hidnplayr 269
 
5663 hidnplayr 270
        lodsd                           ; encoding
271
        DEBUGF  1, "rectangle: width=%u height=%u x=%u y=%u encoding: ",\
272
        [rectangle.width]:2, [rectangle.height]:2, [rectangle.x]:2, [rectangle.y]:2
3545 hidnplayr 273
 
274
        cmp     eax, 0
275
        je      encoding_raw
5666 hidnplayr 276
        cmp     eax, 1
5668 hidnplayr 277
        je      encoding_CopyRect
278
        cmp     eax, 2
279
        je      encoding_RRE
5663 hidnplayr 280
;        cmp     eax, 5
281
;        je      encoding_hextile
282
;        cmp     eax, 15
283
;        je      encoding_TRLE
284
;        cmp     eax, 16
285
;        je      encoding_ZRLE
3545 hidnplayr 286
 
5670 hidnplayr 287
        DEBUGF  2, "unknown encoding: %u\n", eax
3545 hidnplayr 288
        jmp     thread_loop
289
 
5663 hidnplayr 290
next_rectangle:
5670 hidnplayr 291
        inc     [update_framebuffer]
5663 hidnplayr 292
        dec     [rectangles]
293
        jnz     rectangle_loop
294
        jmp     request_fbu
3545 hidnplayr 295
 
296
 
5663 hidnplayr 297
setcolourmapentries:
3545 hidnplayr 298
 
5663 hidnplayr 299
        DEBUGF  1, "Server sent SetColourMapEntries message\n"
3545 hidnplayr 300
 
5677 hidnplayr 301
  @@:
302
        lea     eax, [esi+5]
303
        cmp     [datapointer], eax
304
        jae     @f
305
        call    read_data.more
306
        jmp     @b
307
  @@:
3545 hidnplayr 308
 
5677 hidnplayr 309
        inc     esi             ; padding
310
 
311
        xor     eax, eax
312
        lodsw                   ; first color (just ignore for now)
313
 
314
        lodsw                   ; number of colors (use to find end of message)
315
        xchg    al, ah
316
        lea     eax, [eax*2+eax]
317
        shl     eax, 1
318
  @@:
319
        push    eax
320
        add     eax, esi
321
        cmp     [datapointer], eax
322
        jae     @f
323
        call    read_data.more
324
        pop     eax
325
        jmp     @b
326
  @@:
327
        pop     eax
328
 
329
        add     esi, eax        ; Just skip it for now.
3545 hidnplayr 330
        jmp     thread_loop
331
 
332
 
333
bell:
334
        mcall   55, 55, , , beep
335
        jmp     thread_loop
336
 
337
 
338
servercuttext:
339
 
5663 hidnplayr 340
        DEBUGF  1, "Server cut text\n"
3545 hidnplayr 341
 
5663 hidnplayr 342
  @@:
343
        lea     eax, [esi+7]
344
        cmp     [datapointer], eax
345
        jae     @f
346
        call    read_data.more
347
        jmp     @b
348
  @@:
349
 
350
        add     esi, 3
351
        lodsd
352
        bswap   eax
353
        mov     ecx, eax
354
 
355
  @@:
356
        lea     eax, [esi+ecx]
357
        cmp     [datapointer], eax
358
        jae     @f
359
        call    read_data.more
360
        jmp     @b
361
  @@:
362
 
363
        ; TODO: paste text to clipboard
364
 
365
        DEBUGF  1, "%u bytes of text\n", ecx
366
        add     esi, ecx
3545 hidnplayr 367
        jmp     thread_loop
368
 
369
 
370
read_data:
371
        mov     [datapointer], receive_buffer
5663 hidnplayr 372
        mov     esi, receive_buffer
373
  .more:
374
        push    ebx ecx edx esi edi
5677 hidnplayr 375
        neg     esi
376
        add     esi, receive_buffer + RECEIVE_BUFFER_SIZE
377
        jz      .buffer_end_reached
378
        xor     edi, edi
379
        mcall   recv, [socketnum], [datapointer]
5663 hidnplayr 380
        pop     edi esi edx ecx ebx
3545 hidnplayr 381
        cmp     eax, -1
5677 hidnplayr 382
        je      err_sock
383
        test    eax, eax
384
        jz      err_disconnected
5668 hidnplayr 385
        add     [datapointer], eax
5677 hidnplayr 386
        ret
387
 
388
  .buffer_end_reached:
5668 hidnplayr 389
        ; Buffer is full, first needed data by program is pointed to by esi.
5677 hidnplayr 390
        ; Move all usefull data to begin of buffer
5668 hidnplayr 391
        cmp     esi, receive_buffer
392
        je      err_proto
393
        mov     ecx, [datapointer]
394
        sub     ecx, esi
395
        mov     edi, receive_buffer
396
        rep movsb
5677 hidnplayr 397
        mov     [datapointer], edi      ; new end of data
398
        mov     esi, receive_buffer     ; new start of data
399
        jmp     .more
3545 hidnplayr 400
 
401
 
5677 hidnplayr 402
 
5663 hidnplayr 403
wait_for_data:  ; FIXME: add timeout
5677 hidnplayr 404
        mcall   recv, [socketnum], receive_buffer, 4096, 0      ; MSG_DONTWAIT
3545 hidnplayr 405
        cmp     eax, -1
5677 hidnplayr 406
        je      err_sock
3545 hidnplayr 407
        test    eax, eax
5677 hidnplayr 408
        jz      err_disconnected
5668 hidnplayr 409
        ret
3545 hidnplayr 410
 
5668 hidnplayr 411
 
412
err_disconnected:
413
        mov     [status], STATUS_DISCONNECTED
414
        inc     [update_gui]
415
        mcall   -1
416
 
417
err_dns:
418
        mov     [status], STATUS_DNS_ERR
419
        inc     [update_gui]
420
        mcall   -1
421
 
422
err_sock:
423
        mov     [status], STATUS_SOCK_ERR
424
        inc     [update_gui]
425
        mcall   -1
426
 
427
err_connect:
428
        mov     [status], STATUS_CONNECT_ERR
429
        inc     [update_gui]
430
        mcall   -1
3545 hidnplayr 431
        ret
432
 
5668 hidnplayr 433
err_proto:
434
        mov     [status], STATUS_PROTO_ERR
435
        inc     [update_gui]
5663 hidnplayr 436
        mcall   -1
437
        ret
438
 
5668 hidnplayr 439
err_security:
440
        mov     [status], STATUS_SECURITY_ERR
441
        inc     [update_gui]
442
        mcall   -1
443
        ret
5680 hidnplayr 444
 
445
err_login:
446
        mov     [status], STATUS_LOGIN_FAILED
447
        inc     [update_gui]
448
        mcall   -1
449
        ret