⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftp.erl

📁 OTP是开放电信平台的简称
💻 ERL
字号:
%%%-------------------------------------------------------------------%%% File    : tftp.erl%%% Author  : Hakan Mattsson <hakan@erix.ericsson.se>%%% Description : Trivial FTP%%% Created : 18 May 2004 by Hakan Mattsson <hakan@erix.ericsson.se>%%%-------------------------------------------------------------------%%% %%% This is a complete implementation of the following IETF standards:%%%%%%    RFC 1350, The TFTP Protocol (revision 2).%%%    RFC 2347, TFTP Option Extension.%%%    RFC 2348, TFTP Blocksize Option.%%%    RFC 2349, TFTP Timeout Interval and Transfer Size Options.%%%%%% The only feature that not is implemented in this release is%%% the "netascii" transfer mode.%%%%%% The start/1 function starts a daemon process which, listens for%%% UDP packets on a port. When it receives a request for read or%%% write it spawns a temporary server process which handles the%%% actual transfer of the file. On the client side the read_file/3%%% and write_file/3 functions spawns a temporary client process which%%% establishes contact with a TFTP daemon and performs the actual%%% transfer of the file.%%%%%% Most of the options are common for both the client and the server%%% side, but some of them differs a little. Here are the available%%% options:%%%     %%%   {debug, Level}%%%%%%     Level = none | brief | normal | verbose | all%%%     %%%     Controls the level of debug printouts. The default is none.%%%     %%%   {host, Host}%%%%%%     The name or IP address of the host where the TFTP daemon%%%     resides. This option is only used by the client. See%%%     'inet' about valid host names.%%%     %%%   {port, Port}%%%%%%     Port = integer()%%%     %%%     The TFTP port where the daemon listens. It defaults to the%%%     standardized number 69. On the server side it may sometimes%%%     make sense to set it to 0, which means that the daemon just%%%     will pick a free port (which is returned by the start/1%%%     function).%%%     %%%     If a socket has somehow already has been connected, the%%%     {udp, [{fd, integer()}]} option can be used to pass the%%%     open file descriptor to gen_udp. This can be automated%%%     a bit by using a command line argument stating the%%%     prebound file descriptor number. For example, if the%%%     Port is 69 and the file descriptor 22 has been opened by%%%     setuid_socket_wrap. Then the command line argument%%%     "-tftpd_69 22" will trigger the prebound file%%%     descriptor 22 to be used instead of opening port 69.%%%     The UDP option {udp, [{fd, 22}]} autmatically be added.%%%     See init:get_argument/ about command line arguments and%%%     gen_udp:open/2 about UDP options.%%%%%%   {port_policy, Policy}%%%%%%     Policy = random | Port | {range, MinPort, MaxPort}%%%     Port = MinPort = MaxPort = integer()%%%     %%%     Policy for the selection of the temporary port which is used%%%     by the server/client during the file transfer. It defaults to%%%     'random' which is the standardized policy. With this policy a%%%     randomized free port used. A single port or a range of ports%%%     can be useful if the protocol should pass thru a firewall.%%%   %%%   {prebound_fd, InitArgFlag}%%%%%%     InitArgFlag = atom()%%%%%%     If a socket has somehow already has been connected, the%%%     {udp, [{fd, integer()}]} option can be used to pass the%%%     open file descriptor to gen_udp.%%%%%%     The prebound_fd option makes it possible to pass give the%%%     file descriptor as a command line argument. The typical%%%     usage is when used in conjunction with setuid_socket_wrap%%%     to be able to open privileged sockets. For example if the%%%     file descriptor 22 has been opened by setuid_socket_wrap%%%     and you have choosen my_tftp_fd as init argument, the%%%     command line should like this "erl -my_tftp_fd 22" and %%%     FileDesc should be set to my_tftpd_fd. This would %%%     automatically imply {fd, 22} to be set as UDP option.%%%   %%%   {udp, UdpOptions}%%%%%%      Options to gen_udp:open/2.%%%%%%   {use_tsize, Bool}%%%%%%     Bool = boolean()%%%     %%%     Flag for automated usage of the "tsize" option. With this set%%%     to true, the write_file/3 client will determine the filesize%%%     and send it to the server as the standardized "tsize" option.%%%     A read_file/3 client will just acquire filesize from the%%%     server by sending a zero "tsize".%%%     %%%   {max_tsize, MaxTsize}%%%%%%     MaxTsize = integer() | infinity%%%     %%%     Threshold for the maximal filesize in bytes. The transfer will%%%     be aborted if the limit is exceeded. It defaults to%%%     'infinity'.%%%%%%   {max_conn, MaxConn}%%%   %%%     MaxConn = integer() | infinity%%%     %%%     Threshold for the maximal number of active connections. The%%%     daemon will reject the setup of new connections if the limit%%%     is exceeded. It defaults to 'infinity'.%%%     %%%   {TftpKey, TftpVal}%%%%%%      TftpKey = string()%%%      TftpVal = string()%%%%%%      The name and value of a TFTP option.%%%      %%%   {reject, Feature}%%%   %%%      Feature = Mode | TftpKey%%%      Mode    = read | write%%%      TftpKey = string()%%%      %%%      Control which features that should be rejected.%%%      This is mostly useful for the server as it may restrict%%%      usage of certain TFTP options or read/write access.%%%%%%   {callback, {RegExp, Module, State}}%%%%%%    	 RegExp = string()%%%    	 Module = atom()%%%    	 State  = term()%%%    	 %%%      Registration of a callback module. When a file is to be%%%      transferred, its local filename will be matched to the%%%      regular expressions of the registered callbacks. The first%%%      matching callback will be used the during the transfer.The%%%      callback module must implement the 'tftp' behaviour.%%%%%%      On the server side the callback interaction starts with a%%%      call to open/5 with the registered initial callback%%%      state. open/5 is expected to open the (virtual) file. Then%%%      either the read/1 or write/2 functions are invoked%%%      repeatedly, once per transfererred block. At each function%%%      call the state returned from the previous call is%%%      obtained. When the last block has been encountered the read/1%%%      or write/2 functions is expected to close the (virtual)%%%      file.and return its last state. The abort/3 function is only%%%      used in error situations. prepare/5 is not used on the server%%%      side.%%%      %%%      On the client side the callback interaction is the same, but%%%      it starts and ends a bit differently. It starts with a call%%%      to prepare/5 with the same arguments as open/5%%%      takes. prepare/5 is expected to validate the TFTP options,%%%      suggested by the user and return the subset of them that it%%%      accepts. Then the options is sent to the server which will%%%      perform the same TFTP option negotiation procedure. The%%%      options that are accepted by the server is forwarded to the%%%      open/5 function on the client side. On the client side the%%%      open/5 function must accept all option as is or reject the%%%      transfer. Then the callback interaction follows the same%%%      pattern as described above for the server side. When the last%%%      block is encountered in read/1 or write/2 the returned stated%%%      is forwarded to the user and returned from read_file/3 or%%%      write_file/3.%%%--------------------------------------------------------------------module(tftp).%%-------------------------------------------------------------------%% Interface%%-------------------------------------------------------------------%% public functions-export([	 read_file/3,	 write_file/3,	 start/1,	 info/1,	 change_config/2,	 start/0	]).-export([behaviour_info/1]).behaviour_info(callbacks) ->    [{prepare, 6}, {open, 6}, {read, 1}, {write, 2}, {abort, 3}];behaviour_info(_) ->    undefined.-include("tftp.hrl").%%-------------------------------------------------------------------%% read_file(RemoteFilename, LocalFilename, Options) ->%%   {ok, LastCallbackState} | {error, Reason}%%%% RemoteFilename     = string()%% LocalFilename      = binary | string()%% Options            = [option()]%% LastCallbackState  = term()%% Reason             = term()%%%% Reads a (virtual) file from a TFTP server%%%% If LocalFilename is the atom 'binary', tftp_binary will be used as%% callback module. It will concatenate all transferred blocks and%% return them as one single binary in the CallbackState.%%%% When LocalFilename is a string, it will be matched to the%% registered callback modules and hopefully one of them will be%% selected. By default, tftp_file will be used as callback module. It%% will write each transferred block to the file named%% LocalFilename. The number of transferred bytes will be returned as%% LastCallbackState.%%-------------------------------------------------------------------read_file(RemoteFilename, LocalFilename, Options) ->    tftp_engine:client_start(read, RemoteFilename, LocalFilename, Options).    %%-------------------------------------------------------------------%% write(RemoteFilename, LocalFilename, Options) ->%%   {ok, LastCallbackState} | {error, Reason}%%%% RemoteFilename    = string()%% LocalFilename     = binary() | string()%% Options           = [option()]%% LastCallbackState = term()%% Reason            = term()%%%% Writes a (virtual) file to a TFTP server%% %% If LocalFilename is a binary, tftp_binary will be used as callback%% module. The binary will be transferred block by block and the number%% of transferred bytes will be returned as LastCallbackState.%%%% When LocalFilename is a string, it will be matched to the%% registered callback modules and hopefully one of them will be%% selected. By default, tftp_file will be used as callback module. It%% will read the file named LocalFilename block by block. The number%% of transferred bytes will be returned as LastCallbackState.%%-------------------------------------------------------------------write_file(RemoteFilename, LocalFilename, Options) ->    tftp_engine:client_start(write, RemoteFilename, LocalFilename, Options).%%-------------------------------------------------------------------%% start(Options) -> {ok, Pid} | {error, Reason}%% %% Options = [option()]%% Pid     = pid()%% Reason  = term()%%%% Starts a daemon process which listens for udp packets on a%% port. When it receives a request for read or write it spawns%% a temporary server process which handles the actual transfer%% of the (virtual) file.%%-------------------------------------------------------------------start(Options) ->    tftp_engine:daemon_start(Options).%%-------------------------------------------------------------------%% info(Pid) -> {ok, Options} | {error, Reason}%% %% Options = [option()]%% Reason  = term()%%%% Returns info about a tftp daemon, server or client process%%-------------------------------------------------------------------info(Pid) ->    tftp_engine:info(Pid).%%-------------------------------------------------------------------%% change_config(Pid, Options) -> ok | {error, Reason}%% %% Options = [option()]%% Reason  = term()%%%% Changes config for a tftp daemon, server or client process%% Must be used with care.%%-------------------------------------------------------------------change_config(Pid, Options) ->    tftp_engine:change_config(Pid, Options).%%-------------------------------------------------------------------%% start() -> ok | {error, Reason}%% %% Reason = term()%%%% Start the application%%-------------------------------------------------------------------start() ->    application:start(inets).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -