2019-02-03 13:37:56 -05:00
|
|
|
! Copyright (C) 2019 Doug Coleman.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2019-02-03 18:09:34 -05:00
|
|
|
USING: accessors arrays assocs combinators
|
|
|
|
combinators.short-circuit continuations destructors fry io
|
|
|
|
io.binary io.directories io.encodings.binary io.encodings.latin1
|
|
|
|
io.encodings.string io.encodings.utf8 io.files io.files.info
|
|
|
|
io.sockets kernel math math.parser namespaces pack prettyprint
|
|
|
|
random sequences sequences.extras splitting strings ;
|
2019-02-03 13:37:56 -05:00
|
|
|
IN: protocols.tftp
|
|
|
|
|
|
|
|
CONSTANT: TFTP-RRQ 1 ! Read request (RRQ)
|
|
|
|
CONSTANT: TFTP-WRQ 2 ! Write request (WRQ)
|
|
|
|
CONSTANT: TFTP-DATA 3 ! Data (DATA)
|
|
|
|
CONSTANT: TFTP-ACK 4 ! Acknowledgment (ACK)
|
|
|
|
CONSTANT: TFTP-ERROR 5 ! Error (ERROR)
|
|
|
|
|
|
|
|
GENERIC: get-tftp-host ( server -- host )
|
|
|
|
M: string get-tftp-host resolve-host random host>> 69 <inet4> ;
|
|
|
|
M: integer get-tftp-host "127.0.0.1" swap <inet4> ;
|
|
|
|
M: inet4 get-tftp-host ;
|
|
|
|
M: f get-tftp-host drop "127.0.0.1" 69 <inet4> ;
|
|
|
|
|
|
|
|
: tftp-get ( filename encoding server -- bytes )
|
|
|
|
'[
|
|
|
|
TFTP-RRQ _ _ 3array "Saa" pack-be
|
|
|
|
_ get-tftp-host
|
|
|
|
f 0 <inet4> <datagram> &dispose
|
|
|
|
[ send ] keep
|
|
|
|
dup
|
|
|
|
'[
|
|
|
|
_ receive
|
|
|
|
[ 4 cut swap 2 cut nip be> TFTP-ACK swap 2array "SS" pack-be ] dip
|
|
|
|
_ send
|
|
|
|
dup length 511 >
|
|
|
|
] loop>array* concat
|
|
|
|
] with-destructors ;
|
|
|
|
|
|
|
|
: tftp-get-netascii ( filename server/port/inet4/f -- bytes )
|
|
|
|
"netascii" swap tftp-get latin1 decode ;
|
|
|
|
|
|
|
|
: tftp-get-octet ( filename server/port/inet4/f -- bytes )
|
|
|
|
"octet" swap tftp-get ;
|
|
|
|
|
|
|
|
SYMBOL: tftp-server
|
|
|
|
SYMBOL: tftp-client
|
|
|
|
SYMBOL: clients
|
|
|
|
SYMBOL: tftp-servers
|
|
|
|
tftp-servers [ H{ } clone ] initialize
|
|
|
|
TUPLE: read-file path encoding block ;
|
|
|
|
|
2019-02-03 18:09:34 -05:00
|
|
|
: send-client ( bytes -- )
|
2019-02-03 13:37:56 -05:00
|
|
|
tftp-client get tftp-server get send ;
|
|
|
|
|
2019-02-03 18:09:34 -05:00
|
|
|
: send-error ( message -- )
|
|
|
|
[ TFTP-ERROR 1 ] dip 3array "SSa" pack-be send-client ;
|
|
|
|
|
|
|
|
: send-file-block ( bytes block -- )
|
|
|
|
TFTP-DATA swap 2array "SS" pack-be B{ } prepend-as
|
|
|
|
send-client ;
|
|
|
|
|
2019-02-03 13:37:56 -05:00
|
|
|
: read-file-block ( path n -- bytes )
|
|
|
|
binary swap
|
|
|
|
'[ _ 512 * seek-absolute seek-input 512 read ] with-file-reader ;
|
|
|
|
|
|
|
|
: handle-send-file-next ( block -- )
|
|
|
|
drop
|
|
|
|
tftp-client get clients get ?at [
|
|
|
|
[ [ path>> ] [ block>> ] bi read-file-block ]
|
|
|
|
[ [ 1 + ] change-block block>> ] bi
|
|
|
|
send-file-block
|
|
|
|
] [
|
2019-02-03 18:09:34 -05:00
|
|
|
drop
|
2019-02-03 13:37:56 -05:00
|
|
|
] if ;
|
|
|
|
|
|
|
|
: handle-send-file ( bytes -- )
|
|
|
|
"\0" split harvest first2 [ utf8 decode ] bi@
|
2019-02-03 18:09:34 -05:00
|
|
|
over { [ exists? ] [ file-info directory? not ] } 1&& [
|
|
|
|
"netascii" sequence= utf8 binary ? 0 read-file boa
|
|
|
|
tftp-client get clients get set-at
|
|
|
|
0 handle-send-file-next
|
|
|
|
] [
|
|
|
|
2drop "File not found" send-error
|
|
|
|
] if ;
|
2019-02-03 13:37:56 -05:00
|
|
|
|
|
|
|
: read-tftp-command ( -- )
|
|
|
|
tftp-server get receive tftp-client [
|
|
|
|
2 cut swap be> {
|
|
|
|
{ TFTP-RRQ [ handle-send-file ] }
|
|
|
|
{ TFTP-ACK [ be> handle-send-file-next ] }
|
|
|
|
[ number>string " unimplemented" append throw ]
|
|
|
|
} case
|
|
|
|
] with-variable ;
|
|
|
|
|
|
|
|
: start-tftp-server ( directory port/f -- )
|
|
|
|
get-tftp-host
|
|
|
|
'[
|
|
|
|
H{ } clone clients [
|
|
|
|
_ <datagram> tftp-server [
|
|
|
|
tftp-server get dup addr>> port>> tftp-servers get-global set-at
|
|
|
|
[
|
|
|
|
[ read-tftp-command t ]
|
2019-02-03 18:09:34 -05:00
|
|
|
[ [ . flush ] with-global f ] recover
|
2019-02-03 13:37:56 -05:00
|
|
|
] loop
|
|
|
|
] with-variable
|
|
|
|
] with-variable
|
|
|
|
] with-directory ;
|
|
|
|
|
|
|
|
ERROR: tftp-server-not-running port ;
|
|
|
|
: stop-tftp-server ( port -- )
|
|
|
|
tftp-servers get-global ?delete-at [
|
|
|
|
dispose
|
|
|
|
] [
|
|
|
|
tftp-server-not-running
|
|
|
|
] if ;
|