aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/doc/src/tftp.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/doc/src/tftp.xml')
-rw-r--r--lib/inets/doc/src/tftp.xml637
1 files changed, 637 insertions, 0 deletions
diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml
new file mode 100644
index 0000000000..96d6ae0dd5
--- /dev/null
+++ b/lib/inets/doc/src/tftp.xml
@@ -0,0 +1,637 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2006</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>tftp</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>tftp</module>
+ <modulesummary>Trivial FTP</modulesummary>
+ <description>
+ <p>This is a complete implementation of the following IETF standards:</p>
+ <list type="bulleted">
+ <item>RFC 1350, The TFTP Protocol (revision 2).</item>
+ <item>RFC 2347, TFTP Option Extension.</item>
+ <item>RFC 2348, TFTP Blocksize Option.</item>
+ <item>RFC 2349, TFTP Timeout Interval and Transfer Size Options.</item>
+ </list>
+ <p>The only feature that not is implemented in this release is
+ the "netascii" transfer mode.</p>
+ <p>The <seealso marker="#start/1">start/1</seealso> 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.</p>
+ <p>On the client side
+ the <seealso marker="#read_file/3">read_file/3</seealso>
+ and <seealso marker="#write_file/3">write_file/3</seealso>
+ functions spawns a temporary client process which establishes
+ contact with a TFTP daemon and performs the actual transfer of
+ the file.</p>
+ <p><c>tftp</c> uses a callback module to handle the actual file
+ transfer. Two such callback modules are provided,
+ <c>tftp_binary</c> and <c>tftp_file</c>. See
+ <seealso marker="#read_file/3">read_file/3</seealso> and
+ <seealso marker="#write_file/3">write_file/3</seealso> for
+ more information about these. The user can also implement own
+ callback modules, see <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso> below. A callback module provided by
+ the user is registered using the <c>callback</c> option, see
+ <seealso marker="#options">DATA TYPES</seealso> below.</p>
+ </description>
+
+ <section>
+ <title>TFTP SERVER SERVICE START/STOP </title>
+
+ <p>A TFTP server can be configured to start statically when starting
+ the Inets application. Alternatively it can be started dynamically
+ (when Inets already is started) by calling the Inets application API
+ <c>inets:start(tftpd, ServiceConfig)</c>, or
+ <c>inets:start(tftpd, ServiceConfig, How)</c>,
+ see <seealso marker="inets">inets(3)</seealso> for details.
+ The <c>ServiceConfig</c> for TFTP is described below in
+ the <seealso marker="#options">COMMON DATA TYPES</seealso>
+ section.</p>
+
+ <p>The TFTP server can be stopped using <c>inets:stop(tftpd, Pid)</c>,
+ see <seealso marker="inets">inets(3)</seealso> for details.</p>
+
+ <p>The TPFT client is of such a temporary nature that it is not
+ handled as a service in the Inets service framework.</p>
+
+ </section>
+
+ <section>
+ <marker id="options"></marker>
+ <title>COMMON DATA TYPES</title>
+ <pre>
+ ServiceConfig = Options
+ Options = [option()]
+ option() -- see below
+ </pre>
+ <p>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:</p>
+ <taglist>
+ <tag><c>{debug, Level}</c></tag>
+ <item>
+ <p><c>Level = none | error | warning | brief | normal | verbose | all</c></p>
+ <p>Controls the level of debug printouts. The default is
+ <c>none</c>.</p>
+ </item>
+ <tag><c>{host, Host}</c></tag>
+ <item>
+ <p><c>Host = hostname()</c> see
+ <seealso marker="kernel:inet">inet(3)</seealso></p>
+ <p>The name or IP address of the host where the TFTP daemon
+ resides. This option is only used by the client.</p>
+ </item>
+ <tag><c>{port, Port}</c></tag>
+ <item>
+ <p><c>Port = int()</c></p>
+ <p>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 one is
+ returned by the <c>info/1</c> function).</p>
+ <p>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}]} automatically be added.
+ See init:get_argument/ about command line arguments and
+ gen_udp:open/2 about UDP options.</p>
+ </item>
+ <tag><c>{port_policy, Policy}</c></tag>
+ <item>
+ <p><c>Policy = random | Port | {range, MinPort, MaxPort}</c> <br></br>
+<c>Port = MinPort = MaxPort = int()</c></p>
+ <p>Policy for the selection of the temporary port which is used
+ by the server/client during the file transfer. It defaults to
+ <c>random</c> 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 through a
+ firewall.</p>
+ </item>
+ <tag><c>{udp, Options}</c></tag>
+ <item>
+ <p><c>Options = [Opt]</c> see
+ <seealso marker="kernel:gen_udp#open/1">gen_udp:open/2</seealso></p>
+ </item>
+ <tag><c>{use_tsize, Bool}</c></tag>
+ <item>
+ <p><c>Bool = bool()</c></p>
+ <p>Flag for automated usage of the <c>tsize</c> option. With
+ this set to true, the <c>write_file/3</c> client will
+ determine the filesize and send it to the server as
+ the standardized <c>tsize</c> option. A <c>read_file/3</c>
+ client will just acquire filesize from the server by sending
+ a zero <c>tsize</c>.</p>
+ </item>
+ <tag><c>{max_tsize, MaxTsize}</c></tag>
+ <item>
+ <p><c>MaxTsize = int() | infinity</c></p>
+ <p>Threshold for the maximal filesize in bytes. The transfer
+ will be aborted if the limit is exceeded. It defaults to
+ <c>infinity</c>.</p>
+ </item>
+ <tag><c>{max_conn, MaxConn}</c></tag>
+ <item>
+ <p><c>MaxConn = int() | infinity</c></p>
+ <p>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 <c>infinity</c>.</p>
+ </item>
+ <tag><c>{TftpKey, TftpVal}</c></tag>
+ <item>
+ <p><c>TftpKey = string()</c> <br></br>
+<c>TftpVal = string()</c></p>
+ <p>The name and value of a TFTP option.</p>
+ </item>
+ <tag><c>{reject, Feature}</c></tag>
+ <item>
+ <p><c>Feature = Mode | TftpKey</c> <br></br>
+<c>&nbsp;Mode = read | write</c> <br></br>
+<c>&nbsp;TftpKey = string()</c></p>
+ <p>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.</p>
+ </item>
+ <tag><c>{callback, {RegExp, Module, State}}</c></tag>
+ <item>
+ <p><c>RegExp = string()</c> <br></br>
+<c>Module = atom()</c> <br></br>
+<c>State = term()</c></p>
+ <p>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. See
+ <seealso marker="#read_file/3">read_file/3</seealso> and
+ <seealso marker="#write_file/3">write_file/3</seealso>.
+ </p>
+ <p>The callback module must implement the <c>tftp</c> behavior,
+ <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>.</p>
+ </item>
+
+ <tag><c>{logger, Module}</c></tag>
+ <item>
+ <p><c>Module = module()()</c></p>
+
+ <p>Callback module for customized logging of error, warning and
+ info messages. >The callback module must implement the
+ <c>tftp_logger</c> behavior,
+ <seealso marker="#tftp_logger">LOGGER FUNCTIONS</seealso>.
+ The default module is <c>tftp_logger</c>.</p>
+ </item>
+
+ <tag><c>{max_retries, MaxRetries}</c></tag>
+ <item>
+ <p><c>MaxRetries = int()</c></p>
+
+ <p>Threshold for the maximal number of retries. By default
+ the server/client will try to resend a message up to
+ <c>5</c> times when the timeout expires.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <funcs>
+ <func>
+ <name>start(Options) -> {ok, Pid} | {error, Reason}</name>
+ <fsummary>Start a daemon process</fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>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.</p>
+ </desc>
+ </func>
+ <func>
+ <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <fsummary>Read a (virtual) file from a TFTP server</fsummary>
+ <type>
+ <v>RemoteFilename = string()</v>
+ <v>LocalFilename = binary | string()</v>
+ <v>Options = [option()]</v>
+ <v>LastCallbackState = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP
+ server.</p>
+ <p>If <c>LocalFilename</c> is the atom <c>binary</c>,
+ <c>tftp_binary</c> is used as callback module. It concatenates
+ all transferred blocks and returns them as one single binary
+ in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are no
+ registered callback modules, <c>tftp_file</c> is used as
+ callback module. It writes each transferred block to the file
+ named <c>LocalFilename</c> and returns the number of
+ transferred bytes in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are registered
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
+ </desc>
+ </func>
+ <func>
+ <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <fsummary>Write a (virtual) file to a TFTP server</fsummary>
+ <type>
+ <v>RemoteFilename = string()</v>
+ <v>LocalFilename = binary() | string()</v>
+ <v>Options = [option()]</v>
+ <v>LastCallbackState = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Writes a (virtual) file <c>RemoteFilename</c> to a TFTP
+ server.</p>
+ <p>If <c>LocalFilename</c> is a binary, <c>tftp_binary</c> is
+ used as callback module. The binary is transferred block by
+ block and the number of transferred bytes is returned in
+ <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are no
+ registered callback modules, <c>tftp_file</c> is used as
+ callback module. It reads the file named <c>LocalFilename</c>
+ block by block and returns the number of transferred bytes
+ in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are registered
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(daemons) -> [{Pid, Options}]</name>
+ <fsummary>Return information about all daemons</fsummary>
+ <type>
+ <v>Pid = [pid()()]</v>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns info about all TFTP daemon processes.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(servers) -> [{Pid, Options}]</name>
+ <fsummary>Return information about all servers</fsummary>
+ <type>
+ <v>Pid = [pid()()]</v>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns info about all TFTP server processes.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(Pid) -> {ok, Options} | {error, Reason}</name>
+ <fsummary>Return information about a daemon, server or client process</fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns info about a TFTP daemon, server or client process.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>change_config(daemons, Options) -> [{Pid, Result}]</name>
+ <fsummary>Changes config for all daemons
+ </fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes config for all TFTP daemon processes
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>change_config(servers, Options) -> [{Pid, Result}]</name>
+ <fsummary>Changes config for all servers
+ </fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes config for all TFTP server processes
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>change_config(Pid, Options) -> Result</name>
+ <fsummary>Changes config for a TFTP daemon, server or client process</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Options = [option()]</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes config for a TFTP daemon, server or client process</p>
+ </desc>
+ </func>
+ <func>
+ <name>start() -> ok | {error, Reason}</name>
+ <fsummary>Start the Inets application</fsummary>
+ <type>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Starts the Inets application.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="tftp_callback"></marker>
+ <title>CALLBACK FUNCTIONS</title>
+ <p>A <c>tftp</c> callback module should be implemented as a
+ <c>tftp</c> behavior and export the functions listed below.</p>
+ <p>On the server side the callback interaction starts with a call to
+ <c>open/5</c> with the registered initial callback state.
+ <c>open/5</c> is expected to open the (virtual) file. Then either
+ the <c>read/1</c> or <c>write/2</c> functions are invoked
+ repeatedly, once per transferred block. At each function call
+ the state returned from the previous call is obtained. When
+ the last block has been encountered the <c>read/1</c> or
+ <c>write/2</c> functions is expected to close the (virtual) file
+ and return its last state. The <c>abort/3</c> function is only
+ used in error situations. <c>prepare/5</c> is not used on
+ the server side.</p>
+ <p>On the client side the callback interaction is the same, but it
+ starts and ends a bit differently. It starts with a call to
+ <c>prepare/5</c> with the same arguments as <c>open/5</c> takes.
+ <c>prepare/5</c> 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 are forwarded to the <c>open/5</c> function
+ on the client side. On the client side the <c>open/5</c> 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
+ <c>read/1</c> or <c>write/2</c> the returned state is forwarded to
+ the user and returned from <c>read_file</c>/3 or
+ <c>write_file/3</c>.</p>
+
+ <p> If a callback (which performs the file access
+ in the TFTP server) takes too long time (more than
+ the double TFTP timeout), the server will abort the
+ connection and send an error reply to the client.
+ This implies that the server will release resources
+ attached to the connection faster than before. The
+ server simply assumes that the client has given
+ up.</p>
+
+ <p>If the TFTP server receives yet another request from
+ the same client (same host and port) while it
+ already has an active connection to the client, it
+ will simply ignore the new request if the request is
+ equal with the first one (same filename and options).
+ This implies that the (new) client will be served
+ by the already ongoing connection on the server
+ side. By not setting up yet another connection, in
+ parallel with the ongoing one, the server will
+ consumer lesser resources.
+ </p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <fsummary>Prepare to open a file on the client side</fsummary>
+ <type>
+ <v>Peer = {PeerType, PeerHost, PeerPort}</v>
+ <v>PeerType = inet | inet6</v>
+ <v>PeerHost = ip_address()</v>
+ <v>PeerPort = integer()</v>
+ <v>Access = read | write</v>
+ <v>Filename = string()</v>
+ <v>Mode = string()</v>
+ <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
+ <v>&nbsp;Key = Value = string()</v>
+ <v>InitialState = [] | [{root_dir, string()}]</v>
+ <v>NewState = term()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Prepares to open a file on the client side.</p>
+ <p>No new options may be added, but the ones that are present in
+ <c>SuggestedOptions</c> may be omitted or replaced with new
+ values in <c>AcceptedOptions</c>.</p>
+ <p>Will be followed by a call to <c>open/4</c> before any
+ read/write access is performed. <c>AcceptedOptions</c> is
+ sent to the server which replies with those options that it
+ accepts. These will be forwarded to <c>open/4</c> as
+ <c>SuggestedOptions</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <fsummary>Open a file for read or write access</fsummary>
+ <type>
+ <v>Peer = {PeerType, PeerHost, PeerPort}</v>
+ <v>PeerType = inet | inet6</v>
+ <v>PeerHost = ip_address()</v>
+ <v>PeerPort = integer()</v>
+ <v>Access = read | write</v>
+ <v>Filename = string()</v>
+ <v>Mode = string()</v>
+ <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
+ <v>&nbsp;Key = Value = string()</v>
+ <v>State = InitialState | term()</v>
+ <v>&nbsp;InitialState = [] | [{root_dir, string()}]</v>
+ <v>NewState = term()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Opens a file for read or write access.</p>
+ <p>On the client side where the <c>open/5</c> call has been
+ preceded by a call to <c>prepare/5</c>, all options must be
+ accepted or rejected.</p>
+ <p>On the server side, where there is no preceding
+ <c>prepare/5</c> call, no new options may be added, but
+ the ones that are present in <c>SuggestedOptions</c> may be
+ omitted or replaced with new values in <c>AcceptedOptions</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
+ <fsummary>Read a chunk from the file</fsummary>
+ <type>
+ <v>State = NewState = term()</v>
+ <v>Bin = binary()</v>
+ <v>FileSize = int()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Read a chunk from the file.</p>
+ <p>The callback function is expected to close
+ the file when the last file chunk is
+ encountered. When an error is encountered
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors etc. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+ </desc>
+ </func>
+ <func>
+ <name>write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
+ <fsummary>Write a chunk to the file</fsummary>
+ <type>
+ <v>Bin = binary()</v>
+ <v>State = NewState = term()</v>
+ <v>FileSize = int()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Write a chunk to the file.</p>
+ <p>The callback function is expected to close
+ the file when the last file chunk is
+ encountered. When an error is encountered
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors etc. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+ </desc>
+ </func>
+ <func>
+ <name>abort(Code, Text, State) -> ok</name>
+ <fsummary>Abort the file transfer</fsummary>
+ <type>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>Invoked when the file transfer is aborted.</p>
+ <p>The callback function is expected to clean
+ up its used resources after the aborted file
+ transfer, such as closing open file
+ descriptors etc. The function will not be
+ invoked if any of the other callback
+ functions returns an error, as it is
+ expected that they already have cleaned up
+ the necessary resources. It will however be
+ invoked if the functions fails (crashes).</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="tftp_logger"></marker>
+ <title>LOGGER FUNCTIONS</title>
+
+ <p>A <c>tftp_logger</c> callback module should be implemented as a
+ <c>tftp_logger</c> behavior and export the functions listed below.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>error_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Log an error message</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Log an error message. See <c>error_logger:error_msg/2 for details.</c> </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>warning_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Log an error message</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Log a warning message. See <c>error_logger:warning_msg/2 for details.</c> </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Log an error message</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Log an info message. See <c>error_logger:info_msg/2 for details.</c> </p>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
+
+