Subversion Repositories Kolibri OS

Rev

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