Subversion Repositories Kolibri OS

Rev

Rev 5680 | Rev 5715 | 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"
5708 hidnplayr 188
        mcall   send, [socketnum], SetEncodings, SetEncodings.length, 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
5708 hidnplayr 271
        bswap   eax
5663 hidnplayr 272
        DEBUGF  1, "rectangle: width=%u height=%u x=%u y=%u encoding: ",\
273
        [rectangle.width]:2, [rectangle.height]:2, [rectangle.x]:2, [rectangle.y]:2
3545 hidnplayr 274
 
275
        cmp     eax, 0
276
        je      encoding_raw
5666 hidnplayr 277
        cmp     eax, 1
5668 hidnplayr 278
        je      encoding_CopyRect
279
        cmp     eax, 2
280
        je      encoding_RRE
5663 hidnplayr 281
;        cmp     eax, 5
282
;        je      encoding_hextile
283
;        cmp     eax, 15
284
;        je      encoding_TRLE
285
;        cmp     eax, 16
286
;        je      encoding_ZRLE
3545 hidnplayr 287
 
5670 hidnplayr 288
        DEBUGF  2, "unknown encoding: %u\n", eax
3545 hidnplayr 289
        jmp     thread_loop
290
 
5663 hidnplayr 291
next_rectangle:
5670 hidnplayr 292
        inc     [update_framebuffer]
5663 hidnplayr 293
        dec     [rectangles]
294
        jnz     rectangle_loop
295
        jmp     request_fbu
3545 hidnplayr 296
 
297
 
5663 hidnplayr 298
setcolourmapentries:
3545 hidnplayr 299
 
5663 hidnplayr 300
        DEBUGF  1, "Server sent SetColourMapEntries message\n"
3545 hidnplayr 301
 
5677 hidnplayr 302
  @@:
303
        lea     eax, [esi+5]
304
        cmp     [datapointer], eax
305
        jae     @f
306
        call    read_data.more
307
        jmp     @b
308
  @@:
3545 hidnplayr 309
 
5677 hidnplayr 310
        inc     esi             ; padding
311
 
312
        xor     eax, eax
313
        lodsw                   ; first color (just ignore for now)
314
 
315
        lodsw                   ; number of colors (use to find end of message)
316
        xchg    al, ah
317
        lea     eax, [eax*2+eax]
318
        shl     eax, 1
319
  @@:
320
        push    eax
321
        add     eax, esi
322
        cmp     [datapointer], eax
323
        jae     @f
324
        call    read_data.more
325
        pop     eax
326
        jmp     @b
327
  @@:
328
        pop     eax
329
 
330
        add     esi, eax        ; Just skip it for now.
3545 hidnplayr 331
        jmp     thread_loop
332
 
333
 
334
bell:
335
        mcall   55, 55, , , beep
336
        jmp     thread_loop
337
 
338
 
339
servercuttext:
340
 
5663 hidnplayr 341
        DEBUGF  1, "Server cut text\n"
3545 hidnplayr 342
 
5663 hidnplayr 343
  @@:
344
        lea     eax, [esi+7]
345
        cmp     [datapointer], eax
346
        jae     @f
347
        call    read_data.more
348
        jmp     @b
349
  @@:
350
 
351
        add     esi, 3
352
        lodsd
353
        bswap   eax
354
        mov     ecx, eax
355
 
356
  @@:
357
        lea     eax, [esi+ecx]
358
        cmp     [datapointer], eax
359
        jae     @f
360
        call    read_data.more
361
        jmp     @b
362
  @@:
363
 
364
        ; TODO: paste text to clipboard
365
 
366
        DEBUGF  1, "%u bytes of text\n", ecx
367
        add     esi, ecx
3545 hidnplayr 368
        jmp     thread_loop
369
 
370
 
371
read_data:
372
        mov     [datapointer], receive_buffer
5663 hidnplayr 373
        mov     esi, receive_buffer
374
  .more:
375
        push    ebx ecx edx esi edi
5677 hidnplayr 376
        neg     esi
377
        add     esi, receive_buffer + RECEIVE_BUFFER_SIZE
378
        jz      .buffer_end_reached
379
        xor     edi, edi
380
        mcall   recv, [socketnum], [datapointer]
5663 hidnplayr 381
        pop     edi esi edx ecx ebx
3545 hidnplayr 382
        cmp     eax, -1
5677 hidnplayr 383
        je      err_sock
384
        test    eax, eax
385
        jz      err_disconnected
5668 hidnplayr 386
        add     [datapointer], eax
5677 hidnplayr 387
        ret
388
 
389
  .buffer_end_reached:
5668 hidnplayr 390
        ; Buffer is full, first needed data by program is pointed to by esi.
5677 hidnplayr 391
        ; Move all usefull data to begin of buffer
5668 hidnplayr 392
        cmp     esi, receive_buffer
393
        je      err_proto
394
        mov     ecx, [datapointer]
395
        sub     ecx, esi
396
        mov     edi, receive_buffer
397
        rep movsb
5677 hidnplayr 398
        mov     [datapointer], edi      ; new end of data
399
        mov     esi, receive_buffer     ; new start of data
400
        jmp     .more
3545 hidnplayr 401
 
402
 
5677 hidnplayr 403
 
5663 hidnplayr 404
wait_for_data:  ; FIXME: add timeout
5677 hidnplayr 405
        mcall   recv, [socketnum], receive_buffer, 4096, 0      ; MSG_DONTWAIT
3545 hidnplayr 406
        cmp     eax, -1
5677 hidnplayr 407
        je      err_sock
3545 hidnplayr 408
        test    eax, eax
5677 hidnplayr 409
        jz      err_disconnected
5668 hidnplayr 410
        ret
3545 hidnplayr 411
 
5668 hidnplayr 412
 
413
err_disconnected:
414
        mov     [status], STATUS_DISCONNECTED
415
        inc     [update_gui]
416
        mcall   -1
417
 
418
err_dns:
419
        mov     [status], STATUS_DNS_ERR
420
        inc     [update_gui]
421
        mcall   -1
422
 
423
err_sock:
424
        mov     [status], STATUS_SOCK_ERR
425
        inc     [update_gui]
426
        mcall   -1
427
 
428
err_connect:
429
        mov     [status], STATUS_CONNECT_ERR
430
        inc     [update_gui]
431
        mcall   -1
3545 hidnplayr 432
        ret
433
 
5668 hidnplayr 434
err_proto:
435
        mov     [status], STATUS_PROTO_ERR
436
        inc     [update_gui]
5663 hidnplayr 437
        mcall   -1
438
        ret
439
 
5668 hidnplayr 440
err_security:
441
        mov     [status], STATUS_SECURITY_ERR
442
        inc     [update_gui]
443
        mcall   -1
444
        ret
5680 hidnplayr 445
 
446
err_login:
447
        mov     [status], STATUS_LOGIN_FAILED
448
        inc     [update_gui]
449
        mcall   -1
450
        ret