Subversion Repositories Kolibri OS

Rev

Rev 5720 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. thread_start:
  16.  
  17.         mcall   40, 0                   ; disable all events for this thread
  18.  
  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
  47.         push    esp                     ; reserve stack place
  48.         invoke  getaddrinfo, serveraddr, 0, 0, esp
  49.         pop     esi
  50.         test    eax, eax
  51.         jnz     err_dns
  52.  
  53.         mov     eax, [esi+addrinfo.ai_addr]
  54.         mov     eax, [eax+sockaddr_in.sin_addr]
  55.         mov     [sockaddr1.ip], eax
  56.         invoke  freeaddrinfo, esi
  57.  
  58.         DEBUGF  1, "Connecting to %u.%u.%u.%u:%u\n", \
  59.         [sockaddr1.ip]:1, [sockaddr1.ip+1]:1, [sockaddr1.ip+2]:1, [sockaddr1.ip+3]:1, \
  60.         [sockaddr1.port]:2
  61.  
  62. ; Open socket
  63.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  64.         cmp     eax, -1
  65.         je      err_sock
  66.         mov     [socketnum], eax
  67.  
  68. ; Connect to the server
  69.         mcall   connect, [socketnum], sockaddr1, 18
  70.         cmp     eax, -1
  71.         je      err_connect
  72.  
  73. ; Verify handshake from server
  74.         call    read_data
  75.         cmp     eax, 12
  76.         jb      err_proto
  77.         cmp     dword[esi], "RFB "
  78.         jne     err_proto
  79.         add     esi, 12
  80.  
  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.  
  89. ; Reply to handshake
  90.         DEBUGF  1, "Sending handshake\n"
  91.         mcall   send, [socketnum], HandShake, 12, 0
  92.  
  93. ; VNC 3.3 protocol: server decides security type
  94.         call    read_data
  95.         cmp     eax, 4
  96.         jb      err_proto
  97.         lodsd
  98.         cmp     eax, 0x00000000
  99.         je      err_handshake
  100.         cmp     eax, 0x01000000         ; no security
  101.         je      initialize
  102.         cmp     eax, 0x02000000         ; VNC security
  103.         je      vnc_security
  104.         jmp     err_proto
  105.  
  106. vnc_security:
  107.  
  108.         lea     eax, [esi+8]
  109.         cmp     [datapointer], eax
  110.         jb      err_proto
  111.  
  112.         push    esi     ; pointer to message
  113.  
  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
  180.         mov     esi, [esp]
  181.         mov     ebx, dword[esi+0]
  182.         mov     edx, dword[esi+4]
  183.         call    encrypt_DES
  184.         mov     esi, [esp]
  185.         mov     dword[esi+0], ebx
  186.         mov     dword[esi+4], edx
  187.  
  188.         mov     ebx, dword[esi+8]
  189.         mov     edx, dword[esi+12]
  190.         call    encrypt_DES
  191.         mov     esi, [esp]
  192.         mov     dword[esi+8], ebx
  193.         mov     dword[esi+12], edx
  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
  202.         pop     edx
  203.         mcall   send, [socketnum], , 16, 0
  204.  
  205. securityresult:
  206. ; Wait for SecurityResult from server
  207.         call    read_data
  208.         cmp     eax, 4
  209.         jb      err_proto
  210.         cmp     dword[esi], 0           ; OK
  211.         jne     err_login
  212.  
  213. initialize:
  214.         DEBUGF  1, "Sending ClientInit\n"
  215.         mcall   send, [socketnum], ClientInit, 1, 0
  216.  
  217.         call    read_data               ; now the server should send init message
  218.         cmp     eax, ServerInit.name
  219.         jb      err_proto
  220.  
  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
  226.  
  227.         mov     eax, dword[esi+ServerInit.width]
  228.         mov     dword[FramebufferUpdateRequest.width], eax
  229.         bswap   eax
  230.         mov     dword[screen], eax
  231.         DEBUGF  1, "Screen width=%u, height=%u\n", [screen.width]:2, [screen.height]:2
  232.  
  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.  
  249.         DEBUGF  1, "Sending pixel format\n"
  250. if BITS_PER_PIXEL = 8
  251.         mcall   send, [socketnum], SetPixelFormat8, 20, 0
  252. else if BITS_PER_PIXEL = 16
  253.         mcall   send, [socketnum], SetPixelFormat16, 20, 0
  254. else if BITS_PER_PIXEL = 24
  255.         mcall   send, [socketnum], SetPixelFormat24, 20, 0
  256. else
  257.         mcall   send, [socketnum], SetPixelFormat32, 20, 0
  258. end if
  259.  
  260.         DEBUGF  1, "Sending encoding info\n"
  261.         mcall   send, [socketnum], SetEncodings, SetEncodings.length, 0
  262.  
  263. ; Tell the main thread we are ready for business!
  264.         mov     [status], STATUS_CONNECTED
  265.  
  266. ; Request initial framebuffer update from server
  267.         mov     [FramebufferUpdateRequest.inc], 0
  268.  
  269. request_fbu:
  270.         DEBUGF  1, "Requesting framebuffer update\n"
  271.         mcall   send, [socketnum], FramebufferUpdateRequest, 10, 0
  272.         mov     [FramebufferUpdateRequest.inc], 1
  273.  
  274. thread_loop:
  275.         call    read_data              ; Read the data into the buffer
  276.  
  277.         lodsb
  278.         cmp     al, 0
  279.         je      framebufferupdate
  280.         cmp     al, 1
  281.         je      setcolourmapentries
  282.         cmp     al, 2
  283.         je      bell
  284.         cmp     al, 3
  285.         je      servercuttext
  286.  
  287.         DEBUGF  2, "Unknown server command: %u\n", al
  288.         jmp     thread_loop
  289.  
  290. framebufferupdate:
  291.  
  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
  302.         xchg    al, ah
  303.         mov     [rectangles], ax
  304.         DEBUGF  1, "Framebufferupdate: %u rectangles\n", ax
  305.  
  306. rectangle_loop:
  307.  
  308.   @@:
  309.         lea     eax, [esi+12]
  310.         cmp     [datapointer], eax
  311.         jae     @f
  312.         call    read_data.more
  313.         jmp     @b
  314.   @@:
  315.  
  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
  329.  
  330.         lodsd                           ; encoding
  331.         bswap   eax
  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
  334.  
  335.         cmp     eax, 0
  336.         je      encoding_raw
  337.         cmp     eax, 1
  338.         je      encoding_CopyRect
  339.         cmp     eax, 2
  340.         je      encoding_RRE
  341.         cmp     eax, 15
  342.         je      encoding_TRLE
  343.         cmp     eax, 16
  344.         je      encoding_ZRLE
  345.  
  346.         DEBUGF  2, "unknown encoding: %u\n", eax
  347.         jmp     thread_loop
  348.  
  349. next_rectangle:
  350.         inc     [update_framebuffer]
  351.         dec     [rectangles]
  352.         jnz     rectangle_loop
  353.         jmp     request_fbu
  354.  
  355.  
  356. setcolourmapentries:
  357.  
  358.         DEBUGF  1, "Server sent SetColourMapEntries message\n"
  359.  
  360.   @@:
  361.         lea     eax, [esi+5]
  362.         cmp     [datapointer], eax
  363.         jae     @f
  364.         call    read_data.more
  365.         jmp     @b
  366.   @@:
  367.  
  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.
  389.         jmp     thread_loop
  390.  
  391.  
  392. bell:
  393.         mcall   55, 55, , , beep
  394.         jmp     thread_loop
  395.  
  396.  
  397. servercuttext:
  398.  
  399.         DEBUGF  1, "Server cut text\n"
  400.  
  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
  426.         jmp     thread_loop
  427.  
  428.  
  429. read_data:
  430.         mov     [datapointer], receive_buffer
  431.         mov     esi, receive_buffer
  432.   .more:
  433.         push    ebx ecx edx esi edi
  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]
  439.         pop     edi esi edx ecx ebx
  440.         cmp     eax, -1
  441.         je      err_sock
  442.         test    eax, eax
  443.         jz      err_disconnected
  444.         add     [datapointer], eax
  445.         ret
  446.  
  447.   .buffer_end_reached:
  448.         DEBUGF  1, "end of buffer reached, re-organizing\n"
  449.         pop     edi esi edx ecx ebx
  450.         ; Buffer is full, first needed data by program is pointed to by esi.
  451.         ; Move all usefull data to begin of buffer
  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
  458.         mov     [datapointer], edi      ; new end of data
  459.         mov     esi, receive_buffer     ; new start of data
  460.         jmp     .more
  461.  
  462.  
  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:
  474. ; TODO: distinguish between different socket errors!
  475.         DEBUGF  2, "Socket error: %u\n", ebx
  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
  484.         ret
  485.  
  486. err_proto:
  487.         mov     [status], STATUS_PROTO_ERR
  488.         inc     [update_gui]
  489.         mcall   -1
  490.         ret
  491.  
  492. err_handshake:
  493.         mov     [status], STATUS_SECURITY_ERR
  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.  
  510.         inc     [update_gui]
  511.         mcall   -1
  512.         ret
  513.  
  514. err_login:
  515.         mov     [status], STATUS_LOGIN_FAILED
  516.         inc     [update_gui]
  517.         mcall   -1
  518.         ret
  519.