Subversion Repositories Kolibri OS

Rev

Rev 2581 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;
  2. ; Kolibrios FTP Daemon
  3. ;
  4. ; hidnplayr@gmail.com
  5. ;
  6. ; GPLv2
  7. ;
  8.  
  9. BUFFERSIZE              = 8192
  10.  
  11. STATE_DISCONNECTED      = 0
  12. STATE_CONNECTED         = 1
  13. STATE_LOGIN             = 2
  14. STATE_ACTIVE            = 3
  15.  
  16. TYPE_UNDEF              = 0
  17.  
  18. TYPE_ASCII              = 00000100b
  19. TYPE_EBDIC              = 00001000b
  20. ; subtypes for ascii & ebdic (np = default)
  21. TYPE_NP                 = 00000001b     ; non printable
  22. TYPE_TELNET             = 00000010b
  23. TYPE_ASA                = 00000011b
  24.  
  25. TYPE_IMAGE              = 01000000b     ; binary data
  26. TYPE_LOCAL              = 10000000b     ; bits per byte must be specified
  27.                                         ; lower 4 bits will hold this value
  28.  
  29. MODE_NOTREADY           = 0
  30. MODE_ACTIVE             = 1
  31. MODE_PASSIVE_WAIT       = 2
  32. MODE_PASSIVE_OK         = 3
  33.  
  34. format binary as ""
  35.  
  36. use32
  37.         db      'MENUET01'      ; signature
  38.         dd      1               ; header version
  39.         dd      start           ; entry point
  40.         dd      i_end           ; initialized size
  41.         dd      mem+0x1000      ; required memory
  42.         dd      mem+0x1000      ; stack pointer
  43.         dd      params          ; parameters
  44.         dd      path            ; path
  45.  
  46. include '../macros.inc'
  47. purge mov,add,sub
  48. include '../proc32.inc'
  49. include '../dll.inc'
  50. include '../struct.inc'
  51. include '../libio.inc'
  52.  
  53. include '../network.inc'
  54. include 'commands.inc'
  55.  
  56. align 4
  57. start:
  58. ; load libraries
  59.         stdcall dll.Load, @IMPORT
  60.         test    eax, eax
  61.         jnz     exit
  62.  
  63.         mcall   68, 11                  ; init heap
  64.  
  65. ; find path to main settings file
  66.         mov     edi, path               ; Calculate the length of zero-terminated string
  67.         xor     al, al
  68.         mov     ecx, 1024
  69.         repne   scasb
  70.         dec     edi
  71.         mov     esi, filename           ; append it with '.ini'
  72.         movsd
  73.         movsb
  74.  
  75. ; initialize console
  76.         push    1
  77.         call    [con_start]
  78.  
  79.         push    title
  80.         push    -1
  81.         push    -1
  82.         push    -1
  83.         push    -1
  84.         call    [con_init]
  85.  
  86.         mcall   40, 1 shl 7             ; we only want network events
  87.  
  88.         invoke  ini.get_int, path, str_ftpd, str_port, 21
  89.         mov     [sockaddr1.port], ax
  90.  
  91.         push    eax
  92.         push    str1
  93.         call    [con_printf]
  94.  
  95.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  96.         cmp     eax, -1
  97.         je      sock_err
  98.  
  99.         mov     [socketnum], eax
  100.  
  101.         push    str2
  102.         call    [con_write_asciiz]
  103.  
  104. ;        mcall   setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
  105. ;        cmp     eax, -1
  106. ;        je      opt_err
  107.  
  108.         mcall   bind, [socketnum], sockaddr1, sockaddr1.length
  109.         cmp     eax, -1
  110.         je      bind_err
  111.  
  112.         push    str2
  113.         call    [con_write_asciiz]
  114.  
  115.         invoke  ini.get_int, path, str_ftpd, str_conn, 1        ; Backlog (max connections)
  116.         mov     edx, eax
  117.  
  118.         push    str2
  119.         call    [con_write_asciiz]
  120.  
  121.         mcall   listen, [socketnum]
  122.         cmp     eax, -1
  123.         je      listen_err
  124.  
  125.         push    str2b
  126.         call    [con_write_asciiz]
  127.  
  128. mainloop:
  129.         mcall   10                              ; Wait here for incoming connections on the base socket (socketnum)
  130.  
  131.         mcall   51, 1, threadstart, 0           ; Start a new thread for every incoming connection
  132.                                                 ; NOTE: upon initialisation of the thread, stack will not be available!
  133.         jmp     mainloop
  134.  
  135.         diff16  "threadstart", 0, $
  136. threadstart:
  137.         mcall   68, 12, sizeof.thread_data      ; allocate the thread data struct
  138.         cmp     eax, -1
  139.         je      exit
  140.  
  141.         lea     esp, [eax + thread_data.stack]  ; init stack
  142.         push    eax                             ; save pointer to thread_data on stack
  143.  
  144.         mcall   40, 1 shl 7                     ; we only want network events for this thread
  145.  
  146.         pushd   0x03
  147.         call    [con_set_flags]
  148.         push    str8
  149.         call    [con_write_asciiz]                                              ; print on the console that we have created the new thread successfully
  150.         pushd   0x07
  151.         call    [con_set_flags]
  152.  
  153.         mcall   accept, [socketnum], sockaddr1, sockaddr1.length                ; time to accept the awaiting connection..
  154.         cmp     eax, -1
  155.         je      thread_exit
  156.         mov     edx, [esp]                                                      ; pointer to thread_data
  157.         mov     [edx + thread_data.socketnum], eax
  158.  
  159.         mcall   send, [edx + thread_data.socketnum], str220, str220.length, 0   ; send welcome string to the FTP client
  160.  
  161. threadloop:
  162.         mcall   10
  163.  
  164.         mov     edx, [esp]                                                      ; pointer to thread_data
  165.  
  166.         cmp     [edx + thread_data.mode], MODE_PASSIVE_WAIT
  167.         jne     @f
  168.         mov     ecx, [edx + thread_data.passivesocknum]
  169.         lea     edx, [edx + thread_data.datasock]
  170.         mov     esi, sizeof.thread_data.datasock
  171.         mcall   accept
  172.         mov     edx, [esp]                                                      ; pointer to thread_data
  173.         cmp     eax, -1
  174.         je      @f
  175.         mov     [edx + thread_data.datasocketnum], eax
  176.         mov     [edx + thread_data.mode], MODE_PASSIVE_OK
  177.  
  178.         push    str_datasock
  179.         call    [con_write_asciiz]                                              ; print on the console that the datasock is now ready
  180.        @@:
  181.  
  182.         mov     ecx, [edx + thread_data.socketnum]
  183.         lea     edx, [edx + thread_data.buffer]
  184.         mov     esi, sizeof.thread_data.buffer
  185.         mcall   recv
  186.         cmp     eax, -1                                                         ; error?
  187.         je      threadloop
  188.         or      eax, eax                                                        ; 0 bytes read?
  189.         jz      threadloop
  190.         push    eax                                                             ; save number of bytes read on stack
  191.  
  192.         mov     edx, [esp+4]                                                    ; pointer to thread_data
  193.         mov     byte [edx + thread_data.buffer + eax], 0                        ; append received data with a 0 byte
  194.  
  195.         pushd   0x02                                                            ; print received data to console (in green color)
  196.         call    [con_set_flags]
  197.         push    str_newline
  198.         call    [con_write_asciiz]
  199.         lea     eax, [edx + thread_data.buffer]
  200.         push    eax
  201.         call    [con_write_asciiz]
  202.         pushd   0x07
  203.         call    [con_set_flags]
  204.  
  205.         pop     ecx                                                             ; number of bytes read
  206.         lea     esi, [edx + thread_data.buffer]
  207.         call    parse_cmd
  208.  
  209.         jmp     threadloop
  210.  
  211. listen_err:
  212.         pushd   0x0c
  213.         call    [con_set_flags]
  214.         push    str3
  215.         call    [con_write_asciiz]
  216.         jmp     done
  217.  
  218. bind_err:
  219.         pushd   0x0c
  220.         call    [con_set_flags]
  221.         push    str4
  222.         call    [con_write_asciiz]
  223.         jmp     done
  224.  
  225. sock_err:
  226.         pushd   0x0c
  227.         call    [con_set_flags]
  228.         push    str6
  229.         call    [con_write_asciiz]
  230.         jmp     done
  231.  
  232. done:
  233.         call    [con_getch2]
  234.         push    1
  235.         call    [con_exit]
  236. exit:
  237.         mcall   -1
  238.  
  239.  
  240. thread_exit:
  241.         push    str_bye
  242.         call    [con_write_asciiz]      ; say bye bye
  243.         pop     ecx                     ; get the thread_data pointer from stack
  244.         mcall   68, 13                  ; free the memory
  245.         mcall   -1                      ; and kill the thread
  246.  
  247.  
  248.  
  249. ; initialized data
  250.  
  251. title           db 'KolibriOS FTP daemon 0.1', 0
  252. str1            db 'Starting FTP daemon on port %u', 0
  253. str2            db '.', 0
  254. str2b           db ' OK!',10,0
  255. str3            db 'Listen error',10,0
  256. str4            db 'Bind error',10,0
  257. ;str5            db 'Setsockopt error.',10,10,0
  258. str6            db 'Could not open socket',10,0
  259. str7            db 'Got data!',10,10,0
  260. str8            db 10,'New thread created!',10,0
  261. str_bye         db 10,'Closing thread!',10,0
  262.  
  263. str_logged_in   db 'Login ok',10,0
  264. str_pass_ok     db 'Password ok - Logged in',10,0
  265. str_pwd         db 'Current directory is "%s"\n',0
  266. str_err2        db 'ERROR: cannot open directory',10,0
  267. str_datasock    db 'Passive data socket connected!',10,0
  268. str_notfound    db 'ERROR: file not found',10,0
  269. str_sockerr     db 'ERROR: socket error',10,0
  270.  
  271. str_newline     db 10, 0
  272. str_mask        db '*', 0
  273.  
  274. months          dd 'Jan '
  275.                 dd 'Feb '
  276.                 dd 'Mar '
  277.                 dd 'Apr '
  278.                 dd 'May '
  279.                 dd 'Jun '
  280.                 dd 'Jul '
  281.                 dd 'Aug '
  282.                 dd 'Sep '
  283.                 dd 'Oct '
  284.                 dd 'Nov '
  285.                 dd 'Dec '
  286.  
  287. filename        db '.ini', 0
  288. str_port        db 'port', 0
  289. str_ftpd        db 'ftpd', 0
  290. str_conn        db 'conn', 0
  291.  
  292. sockaddr1:
  293.                 dw AF_INET4
  294.   .port         dw 21
  295.   .ip           dd 0
  296.                 rb 10
  297.   .length       = $ - sockaddr1
  298.  
  299. ; import
  300.  
  301. align 4
  302. @IMPORT:
  303.  
  304. library console,                'console.obj',\
  305.         libini,                 'libini.obj', \
  306.         libio,                  'libio.obj'
  307.  
  308. import  console,\
  309.         con_start,              'START',\
  310.         con_init,               'con_init',\
  311.         con_write_asciiz,       'con_write_asciiz',\
  312.         con_exit,               'con_exit',\
  313.         con_gets,               'con_gets',\
  314.         con_cls,                'con_cls',\
  315.         con_printf,             'con_printf',\
  316.         con_getch2,             'con_getch2',\
  317.         con_set_cursor_pos,     'con_set_cursor_pos',\
  318.         con_set_flags,          'con_set_flags'
  319.  
  320. import  libini,\
  321.         ini.get_str,            'ini_get_str',\
  322.         ini.get_int,            'ini_get_int'
  323.  
  324. import  libio,\
  325.         libio.init,             'lib_init',\
  326.         file.size,              'file_size',\
  327.         file.open,              'file_open',\
  328.         file.read,              'file_read',\
  329.         file.close,             'file_close',\
  330.         file.find.first,        'file_find_first',\
  331.         file.find.next,         'file_find_next',\
  332.         file.find.close,        'file_find_close'
  333.  
  334.  
  335. i_end:
  336.  
  337. ; uninitialised data
  338.  
  339.         socketnum       dd ?
  340.         path            rb 1024
  341.         params          rb 1024
  342.  
  343. mem:
  344.  
  345.  
  346.