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