REBOL [ Title: "TFTP Get" Date: 3-Aug-2003 Version: 1.0.1 File: %tftp-get.r Author: "ND" Purpose: {get file from tftp daemon, could be modified as scheme, needs perfection on write to disk!} Email: none library: [ level: 'intermediate platform: 'all type: 'tool domain: [file-handling files ftp other-net] tested-under: none support: none license: none see-also: none ] ] ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* iofile: "tst.exe" ; filename to get from tftpd tftpd: "192.168.80.1:69" ; tftpd address:port ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* packet-timeout: 0:0:5 block-size: 516 block-cnt: 0 finished: false errorcode: [ "Error not defined, see error message (if any?!)." "File not found." "Access violation." "Disk full allocation exceeded." "Illigal TFTP operation." "Unknown tranfser ID." "File already exists." "No such user." "Network error." "No connection with remote host." ] opcode: make object! [ nul: to-char 00 rrq: to-char 01 wrq: to-char 02 dat: to-char 03 ack: to-char 04 err: to-char 05 ] send-rrq: func [ port [port!] filename [string!] mode [string!] ][ { sends the RRQ packet } if error? try [ insert port rejoin [ opcode/nul opcode/rrq filename opcode/nul mode opcode/nul ]] [ print errorcode/9 ] ] send-ack: func [ port [port!] value] [ { send ACK } insert port rejoin [ opcode/nul opcode/ack block-id value ] ] block-id: func [ value ][ { returns block id from data packet } return block-cnt: join value/3 value/4 ] data-packet?: func [ value { return true if value is data package } ][ either equal? value/2 opcode/dat [ true ][ false ] ] full-packet?: func [ value { check data packet size } ][ either equal? length? value block-size [ true ][ false ] ] print-error: func [ value { print error type } ][ print rejoin [ "Error: " pick errorcode (to-integer value/4) + 1 ] ] perror: func [integer { print tftp error } ][ print rejoin [ "Error: " pick errorcode integer ]] ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ; read from tftpd ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* tftp-get: func [ {get a file by tftp } port [port!] { port to connect to} filename [string!] { filename to get } mode [string!] { octet ascii } /local got [any-type!] ][ send-rrq port filename mode either got: wait [ port packet-timeout ] [ got: copy port ] [print errorcode/10 exit ] ;-- Until last package or error. while [ not finished ] [ either data-packet? got [ either full-packet? got [ ;print rejoin [ "sent ACK" "," ] prin "." send-ack port got write/binary/append to-file iofile remove/part got 4 either got: wait [ port packet-timeout ] [ got: copy port ] [print errorcode/10 exit ] ][ ;-- not a full packet? then last packet! prin "." send-ack port got write/binary/append to-file iofile remove/part got 4 finished: true ] ][ ;-- got error perror (to-integer got/4) + 1 finished: true ] ] ] ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ; main starts here ;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* unset 'udp if exists? to-file iofile [ delete to-file iofile ] print rejoin [ "Writing to: " iofile ] udp: open/no-wait/binary/direct rejoin [ udp:// tftpd ] tftp-get udp iofile "octet" close udp