Subversion Repositories Kolibri OS

Rev

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