Subversion Repositories Kolibri OS

Rev

Rev 5722 | 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
5750 hidnplayr 122
        or      [work], WORK_GUI
5680 hidnplayr 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"
5750 hidnplayr 250
        mcall   send, [socketnum], SetPixelFormat, 20, 0
3545 hidnplayr 251
 
5677 hidnplayr 252
        DEBUGF  1, "Sending encoding info\n"
5708 hidnplayr 253
        mcall   send, [socketnum], SetEncodings, SetEncodings.length, 0
3545 hidnplayr 254
 
5668 hidnplayr 255
; Tell the main thread we are ready for business!
256
        mov     [status], STATUS_CONNECTED
257
 
5715 hidnplayr 258
; Request initial framebuffer update from server
5668 hidnplayr 259
        mov     [FramebufferUpdateRequest.inc], 0
5663 hidnplayr 260
 
261
request_fbu:
262
        DEBUGF  1, "Requesting framebuffer update\n"
5668 hidnplayr 263
        mcall   send, [socketnum], FramebufferUpdateRequest, 10, 0
264
        mov     [FramebufferUpdateRequest.inc], 1
3545 hidnplayr 265
 
266
thread_loop:
267
        call    read_data              ; Read the data into the buffer
268
 
5663 hidnplayr 269
        lodsb
270
        cmp     al, 0
3545 hidnplayr 271
        je      framebufferupdate
5663 hidnplayr 272
        cmp     al, 1
3545 hidnplayr 273
        je      setcolourmapentries
5663 hidnplayr 274
        cmp     al, 2
3545 hidnplayr 275
        je      bell
5663 hidnplayr 276
        cmp     al, 3
3545 hidnplayr 277
        je      servercuttext
278
 
5670 hidnplayr 279
        DEBUGF  2, "Unknown server command: %u\n", al
3545 hidnplayr 280
        jmp     thread_loop
281
 
282
framebufferupdate:
283
 
5663 hidnplayr 284
  @@:
285
        lea     eax, [esi+6]
286
        cmp     [datapointer], eax
287
        jae     @f
288
        call    read_data.more
289
        jmp     @b
290
  @@:
291
 
292
        inc     esi     ; padding
293
        lodsw
3545 hidnplayr 294
        xchg    al, ah
5663 hidnplayr 295
        mov     [rectangles], ax
296
        DEBUGF  1, "Framebufferupdate: %u rectangles\n", ax
3545 hidnplayr 297
 
5663 hidnplayr 298
rectangle_loop:
3545 hidnplayr 299
 
5663 hidnplayr 300
  @@:
301
        lea     eax, [esi+12]
302
        cmp     [datapointer], eax
303
        jae     @f
304
        call    read_data.more
305
        jmp     @b
306
  @@:
3545 hidnplayr 307
 
5668 hidnplayr 308
        xor     eax, eax
309
        lodsw
310
        xchg    al, ah
311
        mov     [rectangle.x], eax
312
        lodsw
313
        xchg    al, ah
314
        mov     [rectangle.y], eax
315
        lodsw
316
        xchg    al, ah
317
        mov     [rectangle.width], eax
318
        lodsw
319
        xchg    al, ah
320
        mov     [rectangle.height], eax
3545 hidnplayr 321
 
5663 hidnplayr 322
        lodsd                           ; encoding
5708 hidnplayr 323
        bswap   eax
5715 hidnplayr 324
        DEBUGF  1, "Rectangle: x=%u y=%u width=%u height=%u encoding: ",\
325
        [rectangle.x]:2, [rectangle.y]:2, [rectangle.width]:2, [rectangle.height]:2
3545 hidnplayr 326
 
327
        cmp     eax, 0
328
        je      encoding_raw
5666 hidnplayr 329
        cmp     eax, 1
5668 hidnplayr 330
        je      encoding_CopyRect
331
        cmp     eax, 2
332
        je      encoding_RRE
5720 hidnplayr 333
        cmp     eax, 15
334
        je      encoding_TRLE
335
        cmp     eax, 16
336
        je      encoding_ZRLE
5750 hidnplayr 337
        cmp     eax, 0xffffff11
338
        je      encoding_cursor
3545 hidnplayr 339
 
5670 hidnplayr 340
        DEBUGF  2, "unknown encoding: %u\n", eax
3545 hidnplayr 341
        jmp     thread_loop
342
 
5663 hidnplayr 343
next_rectangle:
5750 hidnplayr 344
        or      [work], WORK_FRAMEBUFFER
5663 hidnplayr 345
        dec     [rectangles]
346
        jnz     rectangle_loop
347
        jmp     request_fbu
3545 hidnplayr 348
 
349
 
5663 hidnplayr 350
setcolourmapentries:
3545 hidnplayr 351
 
5663 hidnplayr 352
        DEBUGF  1, "Server sent SetColourMapEntries message\n"
3545 hidnplayr 353
 
5677 hidnplayr 354
  @@:
355
        lea     eax, [esi+5]
356
        cmp     [datapointer], eax
357
        jae     @f
358
        call    read_data.more
359
        jmp     @b
360
  @@:
3545 hidnplayr 361
 
5677 hidnplayr 362
        inc     esi             ; padding
363
 
364
        xor     eax, eax
365
        lodsw                   ; first color (just ignore for now)
366
 
367
        lodsw                   ; number of colors (use to find end of message)
368
        xchg    al, ah
369
        lea     eax, [eax*2+eax]
370
        shl     eax, 1
371
  @@:
372
        push    eax
373
        add     eax, esi
374
        cmp     [datapointer], eax
375
        jae     @f
376
        call    read_data.more
377
        pop     eax
378
        jmp     @b
379
  @@:
380
        pop     eax
381
 
382
        add     esi, eax        ; Just skip it for now.
3545 hidnplayr 383
        jmp     thread_loop
384
 
385
 
386
bell:
387
        mcall   55, 55, , , beep
388
        jmp     thread_loop
389
 
390
 
391
servercuttext:
392
 
5663 hidnplayr 393
        DEBUGF  1, "Server cut text\n"
3545 hidnplayr 394
 
5663 hidnplayr 395
  @@:
396
        lea     eax, [esi+7]
397
        cmp     [datapointer], eax
398
        jae     @f
399
        call    read_data.more
400
        jmp     @b
401
  @@:
402
 
403
        add     esi, 3
404
        lodsd
405
        bswap   eax
406
        mov     ecx, eax
407
 
408
  @@:
409
        lea     eax, [esi+ecx]
410
        cmp     [datapointer], eax
411
        jae     @f
412
        call    read_data.more
413
        jmp     @b
414
  @@:
415
 
416
        ; TODO: paste text to clipboard
417
 
418
        DEBUGF  1, "%u bytes of text\n", ecx
419
        add     esi, ecx
3545 hidnplayr 420
        jmp     thread_loop
421
 
422
 
423
read_data:
424
        mov     [datapointer], receive_buffer
5663 hidnplayr 425
        mov     esi, receive_buffer
426
  .more:
427
        push    ebx ecx edx esi edi
5677 hidnplayr 428
        neg     esi
429
        add     esi, receive_buffer + RECEIVE_BUFFER_SIZE
430
        jz      .buffer_end_reached
431
        xor     edi, edi
432
        mcall   recv, [socketnum], [datapointer]
5663 hidnplayr 433
        pop     edi esi edx ecx ebx
3545 hidnplayr 434
        cmp     eax, -1
5677 hidnplayr 435
        je      err_sock
436
        test    eax, eax
437
        jz      err_disconnected
5668 hidnplayr 438
        add     [datapointer], eax
5677 hidnplayr 439
        ret
440
 
441
  .buffer_end_reached:
5720 hidnplayr 442
        DEBUGF  1, "end of buffer reached, re-organizing\n"
443
        pop     edi esi edx ecx ebx
5668 hidnplayr 444
        ; Buffer is full, first needed data by program is pointed to by esi.
5677 hidnplayr 445
        ; Move all usefull data to begin of buffer
5668 hidnplayr 446
        cmp     esi, receive_buffer
447
        je      err_proto
448
        mov     ecx, [datapointer]
449
        sub     ecx, esi
450
        mov     edi, receive_buffer
451
        rep movsb
5677 hidnplayr 452
        mov     [datapointer], edi      ; new end of data
453
        mov     esi, receive_buffer     ; new start of data
454
        jmp     .more
3545 hidnplayr 455
 
456
 
5668 hidnplayr 457
err_disconnected:
458
        mov     [status], STATUS_DISCONNECTED
5750 hidnplayr 459
        or      [work], WORK_GUI
5668 hidnplayr 460
        mcall   -1
461
 
462
err_dns:
463
        mov     [status], STATUS_DNS_ERR
5750 hidnplayr 464
        or      [work], WORK_GUI
5668 hidnplayr 465
        mcall   -1
466
 
467
err_sock:
5722 hidnplayr 468
; TODO: distinguish between different socket errors!
469
        DEBUGF  2, "Socket error: %u\n", ebx
5668 hidnplayr 470
        mov     [status], STATUS_SOCK_ERR
5750 hidnplayr 471
        or      [work], WORK_GUI
5668 hidnplayr 472
        mcall   -1
473
 
474
err_connect:
475
        mov     [status], STATUS_CONNECT_ERR
5750 hidnplayr 476
        or      [work], WORK_GUI
5668 hidnplayr 477
        mcall   -1
3545 hidnplayr 478
        ret
479
 
5668 hidnplayr 480
err_proto:
481
        mov     [status], STATUS_PROTO_ERR
5750 hidnplayr 482
        or      [work], WORK_GUI
5663 hidnplayr 483
        mcall   -1
484
        ret
485
 
5720 hidnplayr 486
err_handshake:
5668 hidnplayr 487
        mov     [status], STATUS_SECURITY_ERR
5720 hidnplayr 488
 
489
        lodsd                   ; Custom message from server?
490
        test    eax, eax
491
        jz      .no_msg
492
        bswap   eax
493
        mov     ecx, eax
494
        cmp     ecx, 512
495
        jb      @f
496
        mov     ecx, 512
497
  @@:
498
        mov     edi, sz_err_security_c
499
        rep movsb
500
        mov     byte[edi], 0
501
        mov     [status], STATUS_SECURITY_ERR_C
502
  .no_msg:
503
 
5750 hidnplayr 504
        or      [work], WORK_GUI
5668 hidnplayr 505
        mcall   -1
506
        ret
5680 hidnplayr 507
 
508
err_login:
509
        mov     [status], STATUS_LOGIN_FAILED
5750 hidnplayr 510
        or      [work], WORK_GUI
5680 hidnplayr 511
        mcall   -1
512
        ret