Subversion Repositories Kolibri OS

Rev

Rev 4655 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2017. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  tftpc.asm - TFTP 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. format binary as ""
  16.  
  17. __DEBUG__       = 0
  18. __DEBUG_LEVEL__ = 1
  19.  
  20. use32
  21.         org     0x0
  22.  
  23.         db      'MENUET01'
  24.         dd      0x1
  25.         dd      START
  26.         dd      I_END
  27.         dd      IM_END+0x1000
  28.         dd      IM_END+0x1000
  29.         dd      0, 0
  30.  
  31. include '../../proc32.inc'
  32. include '../../macros.inc'
  33. include '../../develop/libraries/libs-dev/libio/libio.inc'
  34. include '../../dll.inc'
  35. include '../../develop/libraries/box_lib/trunk/box_lib.mac'
  36.  
  37. include '../../network.inc'
  38. include '../../debug-fdo.inc'
  39.  
  40. TIMEOUT         = 100
  41. buffer_len      = 4096
  42.  
  43. opcode_rrq      = 1 shl 8
  44. opcode_wrq      = 2 shl 8
  45. opcode_data     = 3 shl 8
  46. opcode_ack      = 4 shl 8
  47. opcode_error    = 5 shl 8
  48.  
  49. ; read/write request packet
  50. ;
  51. ;  2 bytes     string    1 byte     string   1 byte
  52. ;  ------------------------------------------------
  53. ; | Opcode |  Filename  |   0  |    Mode    |   0  |
  54. ;  ------------------------------------------------
  55.  
  56. ; data packet
  57. ;
  58. ;  2 bytes     2 bytes      n bytes
  59. ;  ----------------------------------
  60. ; | Opcode |   Block #  |   Data     |
  61. ;  ----------------------------------
  62.  
  63. ; acknowledgement packet
  64. ;
  65. ;  2 bytes     2 bytes
  66. ;  ---------------------
  67. ; | Opcode |   Block #  |
  68. ;  ---------------------
  69.  
  70. ; error packet
  71. ;
  72. ;  2 bytes  2 bytes        string    1 byte
  73. ;  ----------------------------------------
  74. ; | Opcode |  ErrorCode |   ErrMsg   |   0  |
  75. ;  ----------------------------------------
  76.  
  77.  
  78. START:
  79.  
  80.         mcall   68, 11
  81.  
  82.         stdcall dll.Load, @IMPORT
  83.         or      eax, eax
  84.         jnz     exit
  85.  
  86. home:
  87.         mcall   40, EVM_MOUSE + EVM_MOUSE_FILTER + EVM_REDRAW + EVM_BUTTON + EVM_KEY + EVM_STACK
  88.  
  89. redraw:
  90.         call    draw_window
  91.  
  92. mainloop:
  93.         mcall   10
  94.         dec     eax
  95.         jz      redraw
  96.         dec     eax
  97.         jz      key
  98.         dec     eax
  99.         jz      button
  100.  
  101.         invoke  edit_box_mouse, edit1
  102.         invoke  edit_box_mouse, edit2
  103.         invoke  edit_box_mouse, edit3
  104.         invoke  edit_box_mouse, edit4
  105.  
  106.         invoke  option_box_mouse, Option_boxs1
  107.         invoke  option_box_mouse, Option_boxs2
  108.  
  109.         jmp     mainloop
  110.  
  111. button:
  112.         mcall   17
  113.  
  114.         cmp     ah, 0x10        ; connect button
  115.         je      start_transfer
  116.  
  117.         test    ah , ah
  118.         jz      mainloop
  119.  
  120. exit:
  121.         mcall   -1
  122. key:
  123.         mcall   2
  124.  
  125.         invoke  edit_box_key, edit1
  126.         invoke  edit_box_key, edit2
  127.         invoke  edit_box_key, edit3
  128.         invoke  edit_box_key, edit4
  129.  
  130.         jmp     mainloop
  131.  
  132.  
  133. draw_window:
  134. ; get system colors
  135.         mcall   48, 3, sc, 40
  136.  
  137.         mcall   12, 1
  138.  
  139.         mov     edx, [sc.work]
  140.         or      edx, 0x34000000
  141.         xor     esi, esi
  142.         mov     edi, str_title
  143.         mcall   0, 50 shl 16 + 400, 30 shl 16 + 180
  144.  
  145.         mov     ebx, 35 shl 16 + 10
  146.         mov     ecx, 0x80000000
  147.         or      ecx, [sc.work_text]
  148.         mov     edx, str_server
  149.         mcall   4
  150.         mov     ebx, 5 shl 16 + 30
  151.         mov     edx, str_source
  152.         mcall
  153.         mov     ebx, 11 shl 16 + 50
  154.         mov     edx, str_destination
  155.         mcall
  156.         mov     ebx, 47 shl 16 + 72
  157.         mov     edx, str_mode
  158.         mcall
  159.         mov     ebx, 160 shl 16 + 72
  160.         mov     edx, str_method
  161.         mcall
  162.         mov     ebx, 270 shl 16 + 72
  163.         mov     edx, str_blocksize
  164.         mcall
  165.  
  166.         invoke  edit_box_draw, edit1
  167.         invoke  edit_box_draw, edit2
  168.         invoke  edit_box_draw, edit3
  169.         invoke  edit_box_draw, edit4
  170.  
  171.         invoke  option_box_draw, Option_boxs1
  172.         invoke  option_box_draw, Option_boxs2
  173.  
  174.         mov     esi, [sc.work_button]
  175.         mcall   8, 210 shl 16 + 170, 105 shl 16 + 16, 0x10
  176.  
  177.         mcall   38, 10 shl 16 + 380, 130 shl 16 + 130, [sc.work_graph]
  178.  
  179.         cmp     [errormsg], 0
  180.         je      .no_error
  181.  
  182.         mov     ecx, 0x80000000
  183.         or      ecx, [sc.work_text]
  184.         mcall   4, 20 shl 16 + 137, , [errormsg]
  185.         mcall   12, 2
  186.         jmp     .draw_btn
  187.  
  188.   .no_error:
  189.         mov     ecx, 0x80000000
  190.         or      ecx, [sc.work_text]
  191.         mcall   4, 350 shl 16 + 137, , str_kb_s
  192.         mcall   4, 50 shl 16 + 137, , str_complete
  193.         mcall   47, 1 shl 31 + 7 shl 16 + 1, kbps, 305 shl 16 + 137, [sc.work_text]
  194.         mcall   47, 1 shl 31 + 3 shl 16 + 1, done, 25 shl 16 + 137
  195.  
  196.   .draw_btn:
  197.         cmp     [socketnum], 0
  198.         je      .no_transfer
  199.  
  200.         mov     ecx, 0x80000000
  201.         or      ecx, [sc.work_button_text]
  202.         mcall   4, 270 shl 16 + 110, , str_stop
  203.  
  204.         mcall   12, 2
  205.         ret
  206.  
  207.   .no_transfer:
  208.         mov     ecx, 0x80000000
  209.         or      ecx, [sc.work_button_text]
  210.         mcall   4, 260 shl 16 + 110, , str_transfer
  211.  
  212.         mcall   12, 2
  213.         ret
  214.  
  215.  
  216.  
  217. start_transfer:
  218.  
  219. ; resolve the hostname
  220.         mov     [errormsg], str_err_resolve
  221.  
  222.         push    esp     ; reserve stack place
  223.  
  224.         push    esp     ; fourth parameter
  225.         push    0       ; third parameter
  226.         push    0       ; second parameter
  227.         push    dword SRV     ; first parameter
  228.         call    [getaddrinfo]
  229.  
  230.         pop     esi
  231.  
  232.         ; test for error
  233.         test    eax, eax
  234.         jnz     home
  235.  
  236.         mov     eax, [esi + addrinfo.ai_addr]
  237.         mov     eax, [eax + sockaddr_in.sin_addr]
  238.         mov     [sockaddr.ip], eax
  239.  
  240.         ; free allocated memory
  241.         push    esi
  242.         call    [freeaddrinfo]
  243.  
  244. ; Open a socket & connect to server
  245.         mov     [errormsg], str_err_socket
  246.  
  247.         mcall   socket, AF_INET4, SOCK_DGRAM, 0
  248.         cmp     eax, -1
  249.         je      home
  250.         mov     [socketnum], eax
  251.  
  252.         mcall   connect, [socketnum], sockaddr, sockaddr_len
  253.         cmp     eax, -1
  254.         je      home
  255.  
  256. ; Create the read/write request packet
  257.         mov     word[buffer], opcode_rrq
  258.         cmp     [option_group2], op3
  259.         je      @f
  260.         mov     word[buffer], opcode_wrq
  261.       @@:
  262.  
  263. ; Copy in the remote filename (asciiz)
  264.         xor     al, al
  265.         mov     edi, remote_addr
  266.         mov     ecx, 255
  267.         repnz   scasb
  268.         lea     ecx, [edi - remote_addr - 1]
  269.         mov     esi, remote_addr
  270.         mov     edi, buffer+2
  271.         rep     movsb
  272.         stosb
  273.  
  274. ; Append the data type (asciiz)
  275.         cmp     [option_group1], op1
  276.         je      .ascii
  277.         mov     esi, octet
  278.         movsd
  279.         movsb
  280.         jmp     .send_request
  281.  
  282.       .ascii:
  283.         mov     esi, netascii
  284.         movsd
  285.         movsd
  286.  
  287. ; Send the request to the server
  288.       .send_request:
  289.         xor     al, al
  290.         stosb
  291.         lea     esi, [edi - buffer]
  292.         xor     edi, edi
  293.         mcall   send, [socketnum], buffer
  294.         cmp     eax, -1
  295.         je      home
  296.  
  297. ; Jump to send/receive code
  298.         cmp     word[buffer], opcode_wrq
  299.         je      tftp_send
  300.  
  301.  
  302. tftp_receive:
  303.  
  304.         mcall   40, EVM_REDRAW + EVM_BUTTON + EVM_STACK
  305.         mov     [last_ack], 0
  306.         mov     [errormsg], 0
  307.  
  308.         call    draw_window
  309.  
  310. ; Open/create local file
  311.         mov     [file_struct.subfn], 2
  312.         mov     [file_struct.offset], 0
  313.         mov     [file_struct.size], 0
  314.         mcall   70, file_struct
  315.  
  316. ; Truncate it to 0 bytes
  317.         mov     [file_struct.subfn], 4
  318.         mcall   70, file_struct
  319.  
  320. ; Set parameters for writing to file
  321.         mov     [file_struct.subfn], 3
  322.         mov     [file_struct.data], buffer + 4
  323.  
  324.   .loop:
  325.         mcall   23, TIMEOUT
  326.         dec     eax
  327.         jz      .red
  328.         dec     eax
  329.         dec     eax
  330.         jz      .button
  331.  
  332.         mcall   recv, [socketnum], buffer, buffer_len, MSG_DONTWAIT     ; receive data
  333.         cmp     eax, -1
  334.         je      .loop
  335.  
  336.         DEBUGF  1, "Got %u bytes\n", eax
  337.         cmp     word[buffer], opcode_error
  338.         je      tftp_error
  339.         cmp     word[buffer], opcode_data
  340.         jne     .error
  341.  
  342. ; Verify ACK number
  343.         mov     bx, word[buffer + 2]
  344.         rol     bx, 8
  345.         cmp     [last_ack], 0
  346.         je      @f
  347.         cmp     [last_ack], bx
  348.         jne     .packet_got_lost
  349.         inc     bx
  350.       @@:
  351.         mov     [last_ack], bx
  352.  
  353. ; Write to the file
  354.         lea     ecx, [eax - 4]
  355.         mov     [file_struct.size], ecx
  356.         mcall   70, file_struct
  357.         add     [file_struct.offset], ecx
  358.  
  359. ; Send ACK
  360.         mov     word[buffer], opcode_ack
  361.         mcall   send, [socketnum], buffer, 4, 0
  362.         jmp     .loop
  363.  
  364.   .packet_got_lost:
  365.         ;TODO
  366.         jmp     .loop
  367.  
  368.   .red:
  369.         call    draw_window
  370.         jmp     .loop
  371.  
  372.   .button:
  373.         mcall   17
  374.         cmp     ah, 1
  375.         jne     .abort
  376.  
  377.         mcall   close, [socketnum]
  378.         mcall   -1
  379.  
  380.   .abort:
  381.         mcall   close, [socketnum]
  382.         xor     eax, eax
  383.         mov     [socketnum], eax
  384.         mov     [errormsg], str_abort
  385.         jmp     home
  386.  
  387.   .error:
  388.         mcall   close, [socketnum]
  389.         xor     eax, eax
  390.         mov     [socketnum], eax
  391.         mov     [errormsg], str_err_unexp
  392.         jmp     home
  393.  
  394.   .done:
  395.         mcall   close, [socketnum]
  396.         xor     eax, eax
  397.         mov     [socketnum], eax
  398.         mov     [errormsg], str_success
  399.         jmp     home
  400.  
  401.  
  402.  
  403. tftp_send:
  404.  
  405.         mcall   40, EVM_REDRAW + EVM_BUTTON + EVM_STACK
  406.         mov     [last_ack], 0
  407.         mov     [errormsg], 0
  408.  
  409.         call    draw_window
  410.  
  411.         mov     [file_struct.subfn], 0
  412.         mov     [file_struct.offset], 0
  413.         mov     [file_struct.size], buffer_len
  414.         mov     [file_struct.data], buffer + 4
  415.  
  416.   .next:
  417.         mov     edi, buffer
  418.         mov     ax, opcode_data
  419.         stosw
  420.         mov     ax, [last_ack]
  421.         stosw
  422.  
  423.         mcall   70, file_struct
  424.         test    eax, eax
  425. ;        jnz     .done
  426.         mov     [size], ebx
  427.  
  428.   .resend:
  429.         mov     ebx, [size]
  430.         lea     esi, [ebx + 4]
  431.         xor     edi, edi
  432.         mcall   send, [socketnum], buffer
  433.  
  434.   .loop:
  435.         mcall   23, TIMEOUT
  436.         dec     eax
  437.         jz      .red
  438.         dec     eax
  439.         dec     eax
  440.         jz      .button
  441.  
  442.         mcall   recv, [socketnum], buffer, buffer_len, MSG_DONTWAIT
  443.         cmp     eax, -1
  444.         je      .loop
  445.  
  446.         cmp     word[buffer], opcode_error
  447.         je      tftp_error
  448.         cmp     word[buffer], opcode_ack
  449.         jne     .error
  450.  
  451.         mov     ax, [last_ack]
  452.         cmp     word[buffer+2], ax
  453.         jne     .resend
  454.  
  455.         mov     eax, [size]
  456.         cmp     eax, buffer_len
  457.         jb      .done
  458.         add     [file_struct.offset], eax
  459.  
  460.         inc     [last_ack]
  461.         jmp     .next
  462.  
  463.   .red:
  464.         call    draw_window
  465.         jmp     .loop
  466.  
  467.   .button:
  468.         mcall   17
  469.         cmp     ah, 1
  470.         jne     .abort
  471.  
  472.         mcall   close, [socketnum]
  473.         mcall   -1
  474.  
  475.   .abort:
  476.         mcall   close, [socketnum]
  477.         xor     eax, eax
  478.         mov     [socketnum], eax
  479.         mov     [errormsg], str_abort
  480.         jmp     home
  481.  
  482.   .error:
  483.         mcall   close, [socketnum]
  484.         xor     eax, eax
  485.         mov     [socketnum], eax
  486.         mov     [errormsg], str_err_unexp
  487.         jmp     home
  488.  
  489.   .done:
  490.         mcall   close, [socketnum]
  491.         xor     eax, eax
  492.         mov     [socketnum], eax
  493.         mov     [errormsg], str_success
  494.         jmp     home
  495.  
  496.  
  497.  
  498. tftp_error:
  499.         mcall   close, [socketnum]
  500.         xor     eax, eax
  501.         mov     [socketnum], eax
  502.  
  503.         mov     ax, word[buffer+2]
  504.         xchg    al, ah
  505.  
  506.         test    ax, ax
  507.         jz      .0
  508.         dec     ax
  509.         jz      .1
  510.         dec     ax
  511.         jz      .2
  512.         dec     ax
  513.         jz      .3
  514.         dec     ax
  515.         jz      .4
  516.         dec     ax
  517.         jz      .5
  518.         dec     ax
  519.         jz      .6
  520.         dec     ax
  521.         jz      .7
  522.  
  523.   .0:
  524.         mov     [errormsg], str_error.0
  525.         jmp     home
  526.   .1:
  527.         mov     [errormsg], str_error.1
  528.         jmp     redraw
  529.   .2:
  530.         mov     [errormsg], str_error.2
  531.         jmp     home
  532.   .3:
  533.         mov     [errormsg], str_error.3
  534.         jmp     home
  535.   .4:
  536.         mov     [errormsg], str_error.4
  537.         jmp     home
  538.   .5:
  539.         mov     [errormsg], str_error.5
  540.         jmp     home
  541.   .6:
  542.         mov     [errormsg], str_error.6
  543.         jmp     home
  544.   .7:
  545.         mov     [errormsg], str_error.7
  546.         jmp     home
  547.  
  548. ;-------------------------
  549. ; DATA
  550.  
  551. socketnum       dd 0
  552. kbps            dd 0
  553. done            dd 0
  554. errormsg        dd str_welcome
  555.  
  556. sockaddr:
  557.                 dw AF_INET4
  558.                 dw 0x4500       ; 69
  559.   .ip           dd ?
  560. sockaddr_len = $ - sockaddr
  561.  
  562. file_struct:
  563.   .subfn        dd ?
  564.   .offset       dd ?
  565.                 dd 0
  566.   .size         dd ?
  567.   .data         dd ?
  568.                 db 0
  569.   .filename     dd local_addr
  570.  
  571. align 16
  572. @IMPORT:
  573.  
  574. library box_lib         , 'box_lib.obj'         ,\
  575.         network         , 'network.obj'
  576.  
  577. import  box_lib                                 ,\
  578.         edit_box_draw   , 'edit_box'            ,\
  579.         edit_box_key    , 'edit_box_key'        ,\
  580.         edit_box_mouse  , 'edit_box_mouse'      ,\
  581.         version_ed      , 'version_ed'          ,\
  582.         init_checkbox   , 'init_checkbox2'      ,\
  583.         check_box_draw  , 'check_box_draw2'     ,\
  584.         check_box_mouse , 'check_box_mouse2'    ,\
  585.         version_ch      , 'version_ch2'         ,\
  586.         option_box_draw , 'option_box_draw'     ,\
  587.         option_box_mouse, 'option_box_mouse'    ,\
  588.         version_op      , 'version_op'
  589.  
  590. import  network                                 ,\
  591.         inet_ntoa       , 'inet_ntoa'           ,\
  592.         getaddrinfo     , 'getaddrinfo'         ,\
  593.         freeaddrinfo    , 'freeaddrinfo'
  594.  
  595.  
  596. edit1 edit_box 300, 80, 5, 0xffffff, 0x6f9480, 0, 0, 0, 255, SRV, mouse_dd, ed_focus, 13, 13
  597. edit2 edit_box 300, 80, 25, 0xffffff, 0x6f9480, 0, 0, 0, 255, remote_addr, mouse_dd, 0, 4, 4
  598. edit3 edit_box 300, 80, 45, 0xffffff, 0x6f9480, 0, 0, 0, 255, local_addr, mouse_dd, 0, 12, 12
  599. edit4 edit_box 40, 340, 68, 0xffffff, 0x6f9480, 0, 0, 0, 5, BLK, mouse_dd, ed_figure_only, 3, 3
  600.  
  601. op1 option_box option_group1, 80, 68, 6, 12, 0xffffff, 0, 0, netascii, octet-netascii
  602. op2 option_box option_group1, 80, 85, 6, 12, 0xFFFFFF, 0, 0, octet, get-octet
  603.  
  604. op3 option_box option_group2, 210, 68, 6, 12, 0xffffff, 0, 0, get, put-get
  605. op4 option_box option_group2, 210, 85, 6, 12, 0xFFFFFF, 0, 0, put, BLK-put
  606.  
  607. option_group1   dd op1
  608. option_group2   dd op3
  609. Option_boxs1    dd op1, op2, 0
  610. Option_boxs2    dd op3, op4, 0
  611.  
  612. str_title       db 'TFTP client', 0
  613. str_server      db 'Server:', 0
  614. str_source      db 'Remote file:', 0
  615. str_destination db 'Local file:', 0
  616. str_mode        db 'Mode:', 0
  617. str_method      db 'Method:', 0
  618. str_blocksize   db 'Blocksize:', 0
  619. str_kb_s        db 'kB/s', 0
  620. str_complete    db '% complete', 0
  621. str_transfer    db 'Transfer', 0
  622. str_stop        db 'Stop', 0
  623.  
  624. str_error:
  625. .0              db 'Error.', 0                      ; not further defined error
  626. .1              db 'File not found.', 0
  627. .2              db 'Access violation.', 0
  628. .3              db 'Disk full or allocation exceeded.', 0
  629. .4              db 'Illegal TFTP operation.', 0
  630. .5              db 'Unknown transfer ID.', 0
  631. .6              db 'File already exists.', 0
  632. .7              db 'No such user.', 0
  633.  
  634. str_welcome     db 'Welcome.', 0
  635. str_err_resolve db 'Unable to resolve server address.', 0
  636. str_err_socket  db 'Socket error.', 0
  637. str_err_unexp   db 'Unexpected command from server.', 0
  638. str_success     db 'Operation completed successfully.', 0
  639. str_abort       db 'Operation aborted by user.', 0
  640.  
  641. netascii        db 'NetASCII'
  642. octet           db 'Octet'
  643. get             db 'GET'
  644. put             db 'PUT'
  645.  
  646. BLK             db "512", 0, 0, 0
  647.  
  648. SRV             db "192.168.1.115", 0
  649.                 rb (SRV + 256 - $)
  650.  
  651. remote_addr     db "file", 0
  652.                 rb (remote_addr + 256 - $)
  653.  
  654. local_addr      db "/tmp0/1/file", 0
  655.                 rb (local_addr + 256 - $)
  656.  
  657. include_debug_strings
  658.  
  659. I_END:
  660.  
  661. last_ack        dw ?
  662. size            dd ?
  663. mouse_dd        dd ?
  664.  
  665. sc              system_colors
  666.  
  667. buffer          rb buffer_len
  668.  
  669. IM_END: