Subversion Repositories Kolibri OS

Rev

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