1\section{TFTP}
2
3% Short description/overview of module functions
4This module provides support for Trivial File Transfer Protocol (TFTP).
5The support includes client and server implementation, both of them can be active at the same time.
6
7Flows must be split up into TFTP blocks on the sender side, and reassembled from block len
8on the receiving side. Please note that a block whose size is less than the block size indicates
9the end of the transfer. 
10
11To indicate the end of a transfer where the content is aligned with the block size, an additional  
12transmission of zero bytes must follow the flow.
13
14Function pico$\_$tftp$\_$listen must be used to start the server with a proper callback that should be provided by the user. To reject a request received by the server the server callback must call pico$\_$tftp$\_$reject$\_$request.
15
16In order to start transmission or reception of files a session handler must be obtained with a call to pico$\_$tftp$\_$session$\_$setup. The created session may take advantage of the Extenxed Options of the TFTP protocol invoking pico$\_$tftp$\_$set$\_$option before starting using it.
17
18Real file transaction is started using the functions pico$\_$tftp$\_$start$\_$tx and pico$\_$tftp$\_$start$\_$rx; both require a callback that must be provided by the user to handle single chunks of the transmission. The transmitter callback must use pico$\_$tftp$\_$send function to send each block of data.
19
20In case of problem the session can be aborted (and an error message is sent to the remote side) using pico$\_$tftp$\_$abort.
21
22When a transfer is complete the session became invalid and must not be used any more.
23
24\subsection*{Application driven interface}
25
26In some use case is preferable to have an application driven behaviour. The API provide 5 specific functions to use TFTP in this scenario.
27
28The way to obtain a session handler suited for this purpose is an invocation to the function pico$\_$tftp$\_$app$\_$setup. The synchro variable passed to this function will play a key role during the management of the transfer.
29
30As usual the section can be instructed to use Extended Options using pico$\_$tftp$\_$set$\_$option before starting the file transfer.
31
32Once the session is created, the application can start receiving a file with a call to the function pico$\_$tftp$\_$app$\_$start$\_$rx or, if needs to transmit, invoking  pico$\_$tftp$\_$app$\_$start$\_$tx.
33
34After the file transfer is started the user is allowed to perform data handling only when the synchro variable associated with the session is not 0. It is set to 0 after calling pico$\_$tftp$\_$app$\_$setup. A value that differ to 0 means that a single chunk is ready to be handled.
35
36Single chunk of data are received using pico$\_$tftp$\_$get and transmitted with the use of the function pico$\_$tftp$\_$put.
37
38Once the file transfer ends, both for completion or in case of error, the session is no more valid.
39
40
41\subsection{pico\_tftp\_listen}
42
43\subsubsection*{Description}
44Start up a TFTP server listening for GET/PUT requests on the given port.
45The function pointer passed as callback in the \texttt{cb} argument will be invoked upon a new
46transfer request received from the network, and the call will pass the information about:
47\begin{itemize}[noitemsep]
48\item The address of the remote peer asking for a transfer
49\item The remote port of the peer
50\item The type of transfer requested, via the \texttt{opcode} parameter being either \texttt{PICO$\_$TFTP$\_$RRQ} or \texttt{PICO$\_$TFTP$\_$WRQ}, for get or put requests respectively.
51\end{itemize}
52
53\subsubsection*{Function prototype}
54\begin{verbatim}
55int pico_tftp_listen(uint16_t family, void (*cb)(union pico_address *addr,
56                uint16_t port, uint16_t opcode, char *filename, int32_t len));
57\end{verbatim}
58
59\subsubsection*{Parameters}
60\begin{itemize}[noitemsep]
61\item \texttt{family} - The chosen socket family. Accepted values are \texttt{PICO$\_$PROTO$\_$IPV4} for IPv4 and \texttt{PICO$\_$PROTO$\_$IPV6} for IPv6.
62\item \texttt{cb} - a pointer to the callback function, defined by the user, that will be called upon a new transfer request.
63\end{itemize}
64
65\subsubsection*{Return value}
66This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
67
68\subsubsection*{Example}
69\begin{verbatim}
70/* Example of a TFTP listening service callback */
71
72void tftp_listen_cb(union pico_address *addr, uint16_t port,
73                    uint16_t opcode, char *filename, int32_t len)
74{
75    struct note_t *note;
76    struct pico_tftp_session *session;
77
78    printf("TFTP listen callback (BASIC) from remote port %" PRIu16 ".\n",
79           short_be(port));
80    if (opcode == PICO_TFTP_RRQ) {
81        printf("Received TFTP get request for %s\n", filename);
82        note = transfer_prepare(&session, 't', filename, addr, family);
83        start_tx(session, filename, port, cb_tftp_tx, note);
84    } else if (opcode == PICO_TFTP_WRQ) {
85        printf("Received TFTP put request for %s\n", filename);
86        note = transfer_prepare(&session, 'r', filename, addr, family);
87        start_rx(session, filename, port, cb_tftp_rx, note);
88    }
89}
90
91// Code fragment to demostrate the use of pico_tftp_listen:
92if (!is_server_enabled) {
93    pico_tftp_listen(PICO_PROTO_IPV4, (commands->operation == 'S') ?
94                     tftp_listen_cb_opt : tftp_listen_cb);
95    is_server_enabled = 1;
96}
97\end{verbatim}
98
99
100\subsection{pico\_tftp\_reject\_request}
101
102\subsection*{Description}
103This message is used in listen callback to reject a request with an error message.
104\subsection*{Function prototype}
105\begin{verbatim}
106int pico_tftp_reject_request(union pico_address *addr, uint16_t port,
107                             uint16_t error_code, const char *error_message);
108\end{verbatim}
109
110\subsection*{Parameters}
111\begin{itemize}[noitemsep]
112\item \texttt{addr} - The address of the remote peer; it must match the address where the request came from.
113\item \texttt{port} - The port on the remote peer; it must match the address where the request came from.
114\item \texttt{error$\_$code} - Error reason, possible values are:
115
116\begin{tabular}{ll}
117TFTP$\_$ERR$\_$UNDEF & Not defined, see error message (if any) \\
118TFTP$\_$ERR$\_$ENOENT & File not found \\
119TFTP$\_$ERR$\_$EACC & Access violation \\
120TFTP$\_$ERR$\_$EXCEEDED & Disk full or allocation exceeded \\
121TFTP$\_$ERR$\_$EILL & Illegal TFTP operation \\
122TFTP$\_$ERR$\_$ETID & Unknown transfer ID \\
123TFTP$\_$ERR$\_$EEXIST & File already exists \\
124TFTP$\_$ERR$\_$EUSR & No such user \\
125TFTP$\_$ERR$\_$EOPT & Option negotiation \\
126\end{tabular}
127\item \texttt{message} - Text message to attach.
128\end{itemize}
129
130\subsubsection*{Return value}
131This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
132
133\subsection*{Example}
134\begin{verbatim}
135void tftp_listen_cb_opt(union pico_address *addr, uint16_t port,
136                        uint16_t opcode, char *filename, int32_t len)
137{
138    struct note_t *note;
139    struct pico_tftp_session *session;
140    int options;
141    uint8_t timeout;
142    int32_t filesize;
143    int ret;
144
145    printf("TFTP listen callback (OPTIONS) from remote port %" PRIu16 ".\n",
146           short_be(port));
147    /* declare the options we want to support */
148    ret = pico_tftp_parse_request_args(filename, len, &options,
149                                       &timeout, &filesize);
150    if (ret)
151        pico_tftp_reject_request(addr, port, TFTP_ERR_EOPT,
152                                 "Malformed request");
153
154    if (opcode == PICO_TFTP_RRQ) {
155        printf("Received TFTP get request for %s\n", filename);
156        note = transfer_prepare(&session, 'T', filename, addr, family);
157
158        if (options & PICO_TFTP_OPTION_TIME)
159            pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
160        if (options & PICO_TFTP_OPTION_FILE) {
161            ret = get_filesize(filename);
162            if (ret < 0) {
163                pico_tftp_reject_request(addr, port, TFTP_ERR_ENOENT,
164                                         "File not found");
165                return;
166            }
167            pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
168        }
169
170        start_tx(session, filename, port, cb_tftp_tx_opt, note);
171    } else { /* opcode == PICO_TFTP_WRQ */
172        printf("Received TFTP put request for %s\n", filename);
173
174        note = transfer_prepare(&session, 'R', filename, addr, family);
175        if (options & PICO_TFTP_OPTION_TIME)
176            pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
177        if (options & PICO_TFTP_OPTION_FILE)
178            pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
179
180        start_rx(session, filename, port, cb_tftp_rx_opt, note);
181    }
182}
183\end{verbatim}
184
185
186\subsection{pico\_tftp\_session\_setup}
187
188\subsubsection*{Description}
189Obtain a session handler to use for the next file transfer with a remote location.
190
191\subsubsection*{Function prototype}
192\begin{verbatim}
193struct pico_tftp_session * pico_tftp_session_setup(union pico_address *a,
194                                                   uint16_t family);
195\end{verbatim}
196
197\subsubsection*{Parameters}
198\begin{itemize}[noitemsep]
199\item \texttt{a} - The address of the peer to be contacted. In case of a solicited transfer, it must match the address where the request came from.
200\item \texttt{family} - The chosen socket family. Accepted values are \texttt{PICO$\_$PROTO$\_$IPV4} for IPv4 and \texttt{PICO$\_$PROTO$\_$IPV6} for IPv6.
201\end{itemize}
202
203\subsubsection*{Return value}
204In case of success a session handler is returned. In case of failure, NULL is returned and pico$\_$err is set accordingly.
205
206\subsubsection*{Example}
207\begin{verbatim}
208struct pico_tftp_session * make_session_or_die(union pico_address *addr,
209                                               uint16_t family)
210{
211    struct pico_tftp_session * session;
212
213    session = pico_tftp_session_setup(addr, family);
214    if (!session) {
215        fprintf(stderr, "TFTP: Error in session setup\n");
216        exit(3);
217    }
218    return session;
219}
220\end{verbatim}
221
222
223\subsection{pico\_tftp\_set\_option}
224
225\subsection*{Description}
226This function is used to require the use of Extended Options for TFTP transfer associate to a session according to RFC 2347 and RFC 2349. It should be used before the invocation of pico$\_$tftp$\_$start$\_$rx or pico$\_$tftp$\_$start$\_$tx unless the setting is related to the timeout.
227In order to require Transfer size Option PICO$\_$TFTP$\_$OPTION$\_$FILE must be used and its value set to the file size in case of a Write Request or to 0 in case of a Read Request.
228To require to adopt a specific fixed value for the timeout PICO$\_$TFTP$\_$OPTION$\_$TIME must be used with a value ranging between 1 and 255. If this option is set to a value of 0 (or not used at all) an adaptive timeout algorithm will take care of the retransmissions.
229
230\subsection*{Function prototype}
231\begin{verbatim}
232int pico_tftp_set_option(struct pico_tftp_session *session,
233                         uint8_t type, int32_t value);
234\end{verbatim}
235
236\subsection*{Parameters}
237\begin{itemize}[noitemsep]
238\item \texttt{session} - Section handler to use for the file transfer.
239\item \texttt{type} - Option to set; accepted values are PICO$\_$TFTP$\_$OPTION$\_$FILE for Transfer size Option or PICO$\_$TFTP$\_$OPTION$\_$TIME for Timeout interval Option.
240\item \texttt{value} - Option value to send.
241\end{itemize}
242
243\subsubsection*{Return value}
244This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
245
246\subsection*{Example}
247\begin{verbatim}
248filesize = get_filesize(commands->filename);
249if (filesize < 0) {
250    fprintf(stderr, "TFTP: unable to read size of file %s\n",
251            commands->filename);
252    exit(3);
253}
254pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
255start_tx(session, commands->filename, short_be(PICO_TFTP_PORT),
256         cb_tftp_tx_opt, note);
257\end{verbatim}
258
259
260\subsection{pico\_tftp\_get\_option}
261
262\subsection*{Description}
263This function is used to retrieve the values of Extended Options that has been set to a session according to RFC 2347 and RFC 2349.
264In order to ask Transfer size Option value PICO$\_$TFTP$\_$OPTION$\_$FILE must be used; it may be used for example for example in receiver callback for calculation of remaining bytes to be received to complete the current transfer.
265To query the timeout PICO$\_$TFTP$\_$OPTION$\_$TIME must be used; a value ranging between 1 and 255 will be returned in the value parameter if the fixed interval is in place. If the call return -1 and pico$\_$err is set to PICO$\_$ERR$\_$ENOENT the adaptive timeout algorithm is running.
266
267\subsection*{Function prototype}
268\begin{verbatim}
269int pico_tftp_set_option(struct pico_tftp_session *session,
270                         uint8_t type, int32_t *value);
271\end{verbatim}
272
273\subsection*{Parameters}
274\begin{itemize}[noitemsep]
275\item \texttt{session} - Section handler to use for the file transfer.
276\item \texttt{type} - Option to query; accepted values are PICO$\_$TFTP$\_$OPTION$\_$FILE for Transfer size Option or PICO$\_$TFTP$\_$OPTION$\_$TIME for Timeout interval Option.
277\item \texttt{value} - Pointer to an integer variable where to store the value.
278\end{itemize}
279
280\subsubsection*{Return value}
281This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
282
283\subsection*{Example}
284\begin{verbatim}
285int cb_tftp_tx_opt(struct pico_tftp_session *session, uint16_t event,
286                   uint8_t *block, int32_t len, void *arg)
287{
288    int ret;
289    int32_t filesize;
290
291    if (event == PICO_TFTP_EV_OPT) {
292        ret = pico_tftp_get_option(session, PICO_TFTP_OPTION_FILE, &filesize);
293        if (ret)
294            printf("TFTP: Option filesize is not used\n");
295        else
296            printf("TFTP: We expect to transmit %" PRId32 " bytes\n",
297                   filesize);
298        event = PICO_TFTP_EV_OK;
299    }
300
301    return cb_tftp_tx(session, event, block, len, arg);
302}
303\end{verbatim}
304
305
306\subsection{pico\_tftp\_parse\_request\_args}
307
308\subsection*{Description}
309This function is used to extract Extension Options eventually present in Read or Write request (in the listen callback) or in Option ACKnowledge messages (in transmitter or receiver callback when event is equal to PICO$\_$TFTP$\_$EV$\_$OPT).
310Note that timeout and filesize are modified only if the corresponding option is found in the received message.
311
312\subsection*{Function prototype}
313\begin{verbatim}
314int pico_tftp_parse_request_args(char *args, int32_t len, int *options,
315                                 uint8_t *timeout, int32_t *filesize);
316\end{verbatim}
317
318\subsection*{Parameters}
319\begin{itemize}[noitemsep]
320\item \texttt{args} - Pointer to the buffer containing the arguments: filename for listen callback and block for rx or tx callback.
321\item \texttt{len} - Length of the buffer containing the arguments; same value of the len parameter in callbacks.
322\item \texttt{options} - Pointer to the variable that will contain the set of options found. Presence of single options can be then verified anding it with PICO$\_$TFTP$\_$OPTION$\_$FILE or PICO$\_$TFTP$\_$OPTION$\_$TIME.
323\item \texttt{timeout} - Pointer to the variable that will contain the timeout value (if present in the options).
324\item \texttt{filesize} - Pointer to the variable that will contain the filesize value (if present in the options)..
325\end{itemize}
326
327\subsubsection*{Return value}
328This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
329
330\subsection*{Example}
331\begin{verbatim}
332void tftp_listen_cb_opt(union pico_address *addr, uint16_t port,
333                        uint16_t opcode, char *filename, int32_t len)
334{
335    struct note_t *note;
336    struct pico_tftp_session *session;
337    int options;
338    uint8_t timeout;
339    int32_t filesize;
340    int ret;
341
342    printf("TFTP listen callback (OPTIONS) from remote port %" PRIu16 ".\n",
343            short_be(port));
344    /* declare the options we want to support */
345    ret = pico_tftp_parse_request_args(filename, len, &options,
346                                       &timeout, &filesize);
347    if (ret)
348        pico_tftp_reject_request(addr, port, TFTP_ERR_EOPT,
349                                 "Malformed request");
350
351    if (opcode == PICO_TFTP_RRQ) {
352        printf("Received TFTP get request for %s\n", filename);
353        note = transfer_prepare(&session, 'T', filename, addr, family);
354
355        if (options & PICO_TFTP_OPTION_TIME)
356            pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
357        if (options & PICO_TFTP_OPTION_FILE) {
358            ret = get_filesize(filename);
359            if (ret < 0) {
360                pico_tftp_reject_request(addr, port, TFTP_ERR_ENOENT,
361                "File not found");
362                return;
363            }
364            pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
365        }
366
367        start_tx(session, filename, port, cb_tftp_tx_opt, note);
368    } else { /* opcode == PICO_TFTP_WRQ */
369        printf("Received TFTP put request for %s\n", filename);
370
371        note = transfer_prepare(&session, 'R', filename, addr, family);
372        if (options & PICO_TFTP_OPTION_TIME)
373            pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
374        if (options & PICO_TFTP_OPTION_FILE)
375            pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
376
377        start_rx(session, filename, port, cb_tftp_rx_opt, note);
378    }
379}
380\end{verbatim}
381
382
383\subsection{pico\_tftp\_start\_tx}
384
385\subsubsection*{Description}
386Start a TFTP transfer. The action can be unsolicited (client PUT operation) or solicited (server responding to a GET request).
387In either case, the transfer will happen one block at a time, and the callback provided by the user will be called to notify the acknowledgement for the successful of each transfer, transfer of the last block, reception of an option acknowledge message (client mode) or whenever an error occurs. Any error during the TFTP transfer will cancel the transfer itself.
388The possible values for the \texttt{event} variable in callback are:
389\begin{itemize}[noitemsep]
390\item \texttt{PICO$\_$TFTP$\_$EV$\_$OK} Time to send another chunk of data.
391\item \texttt{PICO$\_$TFTP$\_$EV$\_$OPT} Option acknowledge has been received.
392\item \texttt{PICO$\_$TFTP$\_$EV$\_$ERR$\_$PEER} An error has occurred remotely.
393\item \texttt{PICO$\_$TFTP$\_$EV$\_$ERR$\_$LOCAL} An internal error has occurred.
394\end{itemize}
395
396\subsubsection*{Function prototype}
397\begin{verbatim}
398int pico_tftp_start_tx(struct pico_tftp_session *session, uint16_t port,
399        const char *filename,
400        int (*user_cb)(struct pico_tftp_session *session, uint16_t event,
401                       uint8_t *block, int32_t len, void *arg),
402        void *arg);
403\end{verbatim}
404
405\subsubsection*{Parameters}
406\begin{itemize}[noitemsep]
407\item \texttt{session} - Session handler to use for the file transfer.
408\item \texttt{port} - The port on the remote peer.
409\item \texttt{filename} - The name of the file to be transferred. In case of solicited transfer, it must match the filename provided during the request.
410\item \texttt{user$\_$cb} - The callback provided by the user to be called upon each block transfer, option acknowledge or in case of error.
411\item \texttt{arg} - The pointer is sent as argument to the callback.
412\end{itemize}
413
414\subsubsection*{Return value}
415This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
416
417\subsubsection*{Example}
418\begin{verbatim}
419void start_tx(struct pico_tftp_session *session,
420    const char *filename, uint16_t port,
421    int (*tx_callback)(struct pico_tftp_session *session, uint16_t err,
422                       uint8_t *block, int32_t len, void *arg),
423    struct note_t *note)
424{
425    if (pico_tftp_start_tx(session, port, filename, tx_callback, note)) {
426        fprintf(stderr, "TFTP: Error in initialization\n");
427        exit(1);
428    }
429}
430\end{verbatim}
431
432
433\subsection{pico\_tftp\_send}
434\subsubsection*{Description}
435Send the next block during an active TFTP transfer. This is ideally called every time the user callback is triggered by the protocol, indicating that the transfer of the last block has been acknowledged. The user should not call this function unless it's solicited by the protocol during an active transmit session.
436
437\subsubsection*{Function prototype}
438\begin{verbatim}
439int32_t pico_tftp_send(struct pico_tftp_session *session,
440                       const uint8_t *data, int32_t len);
441\end{verbatim}
442
443\subsubsection*{Parameters}
444\begin{itemize}[noitemsep]
445\item \texttt{session} - the session handler to use for the file transfer.
446\item \texttt{data} - the content of the block to be transferred.
447\item \texttt{len} - the size of the buffer being transmitted. If $<$ \texttt{BLOCKSIZE}, the transfer is concluded. In order to terminate a transfer where the content is aligned to \texttt{BLOCKSIZE}, a zero-sized \texttt{pico$\_$tftp$\_$send} must be called at the end of the transfer.
448\end{itemize}
449
450\subsubsection*{Return value}
451In case of success, the number of bytes transmitted is returned. In case of failure, -1 is returned and pico$\_$err is set accordingly.
452
453\subsubsection*{Example}
454\begin{verbatim}
455int cb_tftp_tx(struct pico_tftp_session *session, uint16_t event,
456               uint8_t *block, int32_t len, void *arg)
457{
458    struct note_t *note = (struct note_t *) arg;
459
460    if (event != PICO_TFTP_EV_OK) {
461        fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
462        exit(1);
463    }
464
465    len = read(note->fd, tftp_txbuf, PICO_TFTP_PAYLOAD_SIZE);
466
467    if (len >= 0) {
468        note->filesize += len;
469        pico_tftp_send(session, tftp_txbuf, len);
470        if (len < PICO_TFTP_PAYLOAD_SIZE) {
471            printf("TFTP: file %s (%" PRId32
472                   " bytes) TX transfer complete!\n",
473                   note->filename, note->filesize);
474            close(note->fd);
475            del_note(note);
476        }
477    } else {
478        perror("read");
479        fprintf(stderr,
480                "Filesystem error reading file %s,"
481                " cancelling current transfer\n", note->filename);
482        pico_tftp_abort(session, TFTP_ERR_EACC, "Error on read");
483        del_note(note);
484    }
485
486    if (!clipboard)
487        pico_timer_add(3000, deferred_exit, NULL);
488
489    return len;
490}
491\end{verbatim}
492
493
494\subsection{pico\_tftp\_start\_rx}
495
496\subsubsection*{Description}
497Start a TFTP transfer. The action can be unsolicited (client GET operation) or solicited (server responding to a PUT request).
498In either case, the transfer will happen one block at a time, and the callback provided by the user will be called upon successful transfer of a block, whose content can be directly accessed via the \texttt{block} field, reception of an option acknowledge messagge (client mode) or whenever an error occurs.
499The possible values for the \texttt{event} variable in callback are:
500\begin{itemize}[noitemsep]
501\item \texttt{PICO$\_$TFTP$\_$EV$\_$OK} Previously sent block has been acknowledge.
502\item \texttt{PICO$\_$TFTP$\_$EV$\_$OPT} Option acknowledge has been received.
503\item \texttt{PICO$\_$TFTP$\_$EV$\_$ERR$\_$PEER} An error has occurrend remotely.
504\item \texttt{PICO$\_$TFTP$\_$EV$\_$ERR$\_$LOCAL} An internal error has occurred.
505\end{itemize}
506
507\subsubsection*{Function prototype}
508\begin{verbatim}
509int pico_tftp_start_rx(struct pico_tftp_session *session, uint16_t port,
510        const char *filename,
511        int (*user_cb)(struct pico_tftp_session *session, uint16_t event,
512                       uint8_t *block, int32_t len, void *arg),
513        void *arg);
514\end{verbatim}
515
516\subsubsection*{Parameters}
517\begin{itemize}[noitemsep]
518\item \texttt{session} - the session handler to use for the file transfer.
519\item \texttt{port} - The port on the remote peer.
520\item \texttt{filename} - The name of the file to be transfered. In case of solicited transfer, it must match the filename provided during the request.
521\item \texttt{user$\_$cb} - The callback provided by the user to be called upon each block transfer, option acknowledge or in case of error. This is the callback where the incoming data is processed. When len is less than the block size, the transfer is over.
522\item \texttt{arg} - The pointer sent as argument to the callback.
523\end{itemize}
524
525\subsubsection*{Return value}
526This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
527
528\subsubsection*{Example}
529\begin{verbatim}
530void start_rx(struct pico_tftp_session *session,
531          const char *filename, uint16_t port,
532          int (*rx_callback)(struct pico_tftp_session *session, uint16_t err,
533                             uint8_t *block, int32_t len, void *arg),
534          struct note_t *note)
535{
536    if (pico_tftp_start_rx(session, port, filename, rx_callback, note)) {
537        fprintf(stderr, "TFTP: Error in initialization\n");
538        exit(1);
539    }
540}
541\end{verbatim}
542
543
544\subsection{pico\_tftp\_get\_file\_size}
545
546\subsection*{Description}
547This function is used to retrieve the file size (if transmitted by the remote or set as session option). It is equivalent to a call to pico$\_$tftp$\_$get$\_$option(session, PICO$\_$TFTP$\_$OPTION$\_$FILE, $\&$file$\_$size);
548
549\subsection*{Function prototype}
550\begin{verbatim}
551int pico_tftp_get_file_size(struct pico_tftp_session *session,
552                            int32_t *file_size);
553\end{verbatim}
554
555\subsection*{Parameters}
556\begin{itemize}[noitemsep]
557\item \texttt{session} - Section handler to use for the file transfer.
558\item \texttt{file$\_$size} - Pointer to an integer variable where to store the value.
559\end{itemize}
560
561\subsubsection*{Return value}
562This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
563
564\subsection*{Example}
565\begin{verbatim}
566ret = pico_tftp_get_file_size(session, &file_size);
567if (ret)
568    printf("Information about file size has not been received"\n);
569\end{verbatim}
570
571
572\subsection{pico\_tftp\_abort}
573\subsubsection*{Description}
574When called this function aborts associated ongoing transmission and notifying the other endpoint with a proper error message. After a call to this function the session is closed automatically.
575
576\subsubsection*{Function prototype}
577\begin{verbatim}
578int pico_tftp_abort(struct pico_tftp_session *session,
579                    uint16_t error, const char *reason);
580\end{verbatim}
581
582\subsubsection*{Parameters}
583\begin{itemize}[noitemsep]
584\item \texttt{session} - the session handler related to the session to abort.
585\item \texttt{error} - Error reason code, possible values are:
586
587\begin{tabular}{ll}
588TFTP$\_$ERR$\_$UNDEF & Not defined, see error message (if any) \\
589TFTP$\_$ERR$\_$ENOENT & File not found \\
590TFTP$\_$ERR$\_$EACC & Access violation \\
591TFTP$\_$ERR$\_$EXCEEDED & Disk full or allocation exceeded \\
592TFTP$\_$ERR$\_$EILL & Illegal TFTP operation \\
593TFTP$\_$ERR$\_$ETID & Unknown transfer ID \\
594TFTP$\_$ERR$\_$EEXIST & File already exists \\
595TFTP$\_$ERR$\_$EUSR & No such user \\
596TFTP$\_$ERR$\_$EOPT & Option negotiation \\
597\end{tabular}
598\item \texttt{reason} - Text message to attach.
599\end{itemize}
600
601\subsubsection*{Return value}
602This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
603
604\subsection*{Example}
605\begin{verbatim}
606int cb_tftp_rx(struct pico_tftp_session *session, uint16_t event,
607               uint8_t *block, int32_t len, void *arg)
608{
609    struct note_t *note = (struct note_t *) arg;
610    int ret;
611
612    if (event != PICO_TFTP_EV_OK) {
613        fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
614        exit(1);
615    }
616
617    note->filesize += len;
618    if (write(note->fd, block, len) < 0) {
619        perror("write");
620        fprintf(stderr, "Filesystem error writing file %s,"
621                " cancelling current transfer\n", note->filename);
622        pico_tftp_abort(session, TFTP_ERR_EACC, "Error on write");
623        del_note(note);
624    } else {
625        if (len != PICO_TFTP_PAYLOAD_SIZE) {
626            printf("TFTP: file %s (%" PRId32
627                   " bytes) RX transfer complete!\n",
628                   note->filename, note->filesize);
629            close(note->fd);
630            del_note(note);
631        }
632    }
633
634    if (!clipboard)
635        pico_timer_add(3000, deferred_exit, NULL);
636
637    return len;
638}
639\end{verbatim}
640
641
642\subsection{pico\_tftp\_close\_server}
643
644\subsection*{Description}
645This function is used to shutdown the TFTP server.
646
647\subsection*{Function prototype}
648\begin{verbatim}
649int pico_tftp_close_server(void);
650\end{verbatim}
651
652\subsubsection*{Return value}
653This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
654
655\subsection*{Example}
656\begin{verbatim}
657ret = pico_tftp_close_server();
658if (ret)
659    printf(stderr, "Failure shutting down the server\n");
660\end{verbatim}
661
662
663\subsection{pico\_tftp\_app\_setup}
664
665\subsection*{Description}
666Obtain a session handler to use for the next file transfer with a remote location in application driven mode.
667
668\subsection*{Function prototype}
669\begin{verbatim}
670struct pico_tftp_session * pico_tftp_app_setup(union pico_address *a,
671        uint16_t port, uint16_t family, int *synchro);
672\end{verbatim}
673
674\subsection*{Parameters}
675\begin{itemize}[noitemsep]
676\item \texttt{a} - The address of the peer to be contacted. In case of a solicited transfer, it must match the address where the request came from.
677\item \texttt{port} - The port on the remote peer.
678\item \texttt{family} - The chosen socket family. Accepted values are \texttt{PICO$\_$PROTO$\_$IPV4} for IPv4 and \texttt{PICO$\_$PROTO$\_$IPV6} for IPv6.
679\item \texttt{synchro} - Variable to handle the synchronization.
680\end{itemize}
681
682\subsubsection*{Return value}
683In case of success a session handler is returned. In case of failure, NULL is returned and pico$\_$err is set accordingly.
684
685\subsection*{Example}
686\begin{verbatim}
687session = pico_tftp_app_setup(&server_address, short_be(PICO_TFTP_PORT),
688                              PICO_PROTO_IPV4, &synchro);
689if (!session) {
690    fprintf(stderr, "Error in pico_tftp_app_setup\n");
691    exit(1);
692}
693\end{verbatim}
694
695
696\subsection{pico\_tftp\_app\_start\_rx}
697
698\subsection*{Description}
699Application driven function used to request to read a remote file. The transfer will happen one block at a time using pico$\_$tftp$\_$app$\_$get.
700
701\subsection*{Function prototype}
702\begin{verbatim}
703int pico_tftp_app_start_rx(struct pico_tftp_session *session,
704                           const char *filename);
705\end{verbatim}
706
707\subsection*{Parameters}
708\begin{itemize}[noitemsep]
709\item \texttt{session} - Session handler to use for the file transfer.
710\item \texttt{filename} - The name of the file to be received.
711\end{itemize}
712
713\subsubsection*{Return value}
714This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
715
716\subsection*{Example}
717\begin{verbatim}
718printf("Start receiving file %s with options set to %d\n", filename, options);
719
720if (options) {
721    ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0);
722    if (ret) {
723        fprintf(stderr, "Error in pico_tftp_set_option\n");
724        exit(1);
725    }
726}
727
728ret = pico_tftp_app_start_rx(session, filename);
729if (ret) {
730    fprintf(stderr, "Error in pico_tftp_app_start_rx\n");
731    exit(1);
732}
733\end{verbatim}
734
735
736\subsection{pico\_tftp\_app\_start\_tx}
737
738\subsection*{Description}
739Application driven function used to request to write a remote file. The transfer will happen one block at a time using pico$\_$tftp$\_$app$\_$put.
740
741\subsection*{Function prototype}
742\begin{verbatim}
743int pico_tftp_app_start_tx(struct pico_tftp_session *session,
744                           const char *filename);
745\end{verbatim}
746
747\subsection*{Parameters}
748\begin{itemize}[noitemsep]
749\item \texttt{session} - Session handler to use for the file transfer.
750\item \texttt{filename} - The name of the file to be sent.
751\end{itemize}
752
753\subsubsection*{Return value}
754This function returns 0 if succeeds or -1 in case of errors (pico$\_$err is set accordingly).
755
756\subsection*{Example}
757\begin{verbatim}
758printf("Start sending file %s with options set to %d\n", filename, options);
759
760if (options) {
761    ret = get_filesize(filename);
762    if (ret < 0) {
763        fprintf(stderr, "Error in get_filesize\n");
764        exit(1);
765    }
766
767    ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
768    if (ret) {
769        fprintf(stderr, "Error in pico_tftp_set_option\n");
770        exit(1);
771    }
772}
773
774ret = pico_tftp_app_start_tx(session, filename);
775if (ret) {
776    fprintf(stderr, "Error in pico_tftp_app_start_rx\n");
777    exit(1);
778}
779\end{verbatim}
780
781
782\subsection{pico\_tftp\_get}
783
784\subsection*{Description}
785Read the next block during an active TFTP transfer. The len field must always be equal to PICO$\_$TFTP$\_$PAYLOAD$\_$SIZE. Once the file has been sent or after an error the session is no more valid.
786
787\subsection*{Function prototype}
788\begin{verbatim}
789int32_t pico_tftp_get(struct pico_tftp_session *session,
790                      uint8_t *data, int32_t len);
791\end{verbatim}
792
793\subsection*{Parameters}
794\begin{itemize}[noitemsep]
795\item \texttt{session} - Session handler to use for the file transfer.
796\item \texttt{data} - Buffer where to store the acquired payload.
797\item \texttt{len} - Length of the buffer size to receive; it is equal to the fixed chunk size.
798\end{itemize}
799
800\subsubsection*{Return value}
801This function returns the number of received bytes of payload (0 included) if succeeds. In case of error a negative number is returned.
802
803\subsubsection*{Errors}
804\begin{itemize}[noitemsep]
805\item \texttt{-1} At least one of the passed arguments are invalid.
806\item \texttt{-PICO$\_$TFTP$\_$EV$\_$ERR$\_$PEER} Remote failure.
807\item \texttt{-PICO$\_$TFTP$\_$EV$\_$ERR$\_$LOCAL} Local failure.
808\end{itemize}
809
810\subsection*{Example}
811\begin{verbatim}
812for(;left; left -= countdown) {
813    usleep(2000); //PICO_IDLE();
814    pico_stack_tick();
815    if (countdown)
816        continue;
817
818    if (*synchro) {
819        len = pico_tftp_get(session, buf, PICO_TFTP_PAYLOAD_SIZE);
820        if (len < 0) {
821            fprintf(stderr, "Failure in pico_tftp_get\n");
822            close(fd);
823            countdown = 1;
824            continue;
825        }
826        ret = write(fd, buf, len);
827        if (ret < 0) {
828            fprintf(stderr, "Error in write\n");
829            pico_tftp_abort(session, TFTP_ERR_EXCEEDED, "File write error");
830            close(fd);
831            countdown = 1;
832            continue;
833        }
834        printf("Written %" PRId32 " bytes to file (synchro=%d)\n",
835               len, *synchro);
836
837        if (len != PICO_TFTP_PAYLOAD_SIZE) {
838            close(fd);
839            printf("Transfer complete!\n");
840            countdown = 1;
841        }
842    }
843}
844\end{verbatim}
845
846
847\subsection{pico\_tftp\_put}
848
849\subsection*{Description}
850Send the next block during an active TFTP transfer. The len field, with the exception of last invocation must always be equal to PICO$\_$TFTP$\_$PAYLOAD$\_$SIZE. Once the file has been sent or after an error the session is no more valid.
851
852\subsection*{Function prototype}
853\begin{verbatim}
854int32_t pico_tftp_put(struct pico_tftp_session *session,
855                      uint8_t *data, int32_t len);
856\end{verbatim}
857
858\subsection*{Parameters}
859\begin{itemize}[noitemsep]
860\item \texttt{session} - Session handler to use for the file transfer.
861\item \texttt{data} - Pointer to the data to be transmitted.
862\item \texttt{len} - Length of the buffer size to transmit; last chunk must be $<$ of the maximum buffer size (0 if file size was a multiple of maximum buffer size).
863
864\end{itemize}
865
866\subsubsection*{Return value}
867This function returns the number of transmitted payload data (len) if succeeds. In case of error a negative number is returned.
868
869\subsubsection*{Errors}
870\begin{itemize}[noitemsep]
871\item \texttt{-1} At least one of the passed arguments are invalid.
872\item \texttt{-PICO$\_$TFTP$\_$EV$\_$ERR$\_$PEER} Remote failure.
873\item \texttt{-PICO$\_$TFTP$\_$EV$\_$ERR$\_$LOCAL} Local failure.
874\end{itemize}
875
876\subsection*{Example}
877\begin{verbatim}
878for(;left; left -= countdown) {
879    usleep(2000); //PICO_IDLE();
880    pico_stack_tick();
881    if (countdown)
882        continue;
883
884    if (*synchro) {
885        ret = read(fd, buf, PICO_TFTP_PAYLOAD_SIZE);
886        if (ret < 0) {
887            fprintf(stderr, "Error in read\n");
888            pico_tftp_abort(session, TFTP_ERR_EACC, "File read error");
889            close(fd);
890            countdown = 1;
891            continue;
892        }
893        printf("Read %" PRId32 " bytes from file (synchro=%d)\n",
894               len, *synchro);
895
896        len = pico_tftp_put(session, buf, ret);
897        if (len < 0) {
898            fprintf(stderr, "Failure in pico_tftp_put\n");
899            close(fd);
900            countdown = 1;
901            continue;
902        }
903
904        if (len != PICO_TFTP_PAYLOAD_SIZE) {
905            close(fd);
906            printf("Transfer complete!\n");
907            countdown = 1;
908        }
909    }
910}
911\end{verbatim}
912