iot_tftp.c 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455
  1. /**
  2. * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_config.h"
  41. #include "iot_tftp.h"
  42. #include "iot_common.h"
  43. #include "udp_api.h"
  44. #include "app_util.h"
  45. #if TFTP_CONFIG_LOG_ENABLED
  46. #define NRF_LOG_MODULE_NAME tftp
  47. #define NRF_LOG_LEVEL TFTP_CONFIG_LOG_LEVEL
  48. #define NRF_LOG_INFO_COLOR TFTP_CONFIG_INFO_COLOR
  49. #define NRF_LOG_DEBUG_COLOR TFTP_CONFIG_DEBUG_COLOR
  50. #include "nrf_log.h"
  51. NRF_LOG_MODULE_REGISTER();
  52. #define TFTP_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  53. #define TFTP_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  54. #define TFTP_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  55. #define TFTP_ENTRY() TFTP_TRC(">> %s", __func__)
  56. #define TFTP_EXIT() TFTP_TRC("<< %s", __func__)
  57. #else // TFTP_CONFIG_LOG_ENABLED
  58. #define TFTP_TRC(...) /**< Disables traces. */
  59. #define TFTP_DUMP(...) /**< Disables dumping of octet streams. */
  60. #define TFTP_ERR(...) /**< Disables error logs. */
  61. #define TFTP_ENTRY(...)
  62. #define TFTP_EXIT(...)
  63. #endif // TFTP_CONFIG_LOG_ENABLED
  64. /**
  65. * @defgroup tftp_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
  66. *
  67. * @details Macros used to lock and unlock modules. Currently, SDK does not use mutexes but
  68. * framework is provided in case need arises to use an alternative architecture.
  69. * @{
  70. */
  71. #define TFTP_MUTEX_LOCK() SDK_MUTEX_LOCK(m_tftp_mutex) /**< Lock module using mutex. */
  72. #define TFTP_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_tftp_mutex) /**< Unlock module using mutex. */
  73. /** @} */
  74. #define TFTP_HEADER_SIZE 2 /**< uint16_t opcode number. */
  75. #define TFTP_BLOCK_ID_SIZE 2 /**< uint16_t block id number. */
  76. #define TFTP_ERR_CODE_SIZE 2 /**< uint16_t error code. */
  77. #define TFTP_DEFAULT_BLOCK_SIZE 512 /**< uint16_t default data block size. */
  78. #define TFTP_DEFAULT_PORT 69 /**< uint16_t default TFTP server port number. */
  79. /**@brief Supported TFTP options. */
  80. #define OPTION_MODE_ASCII "netascii" /**< NETASCII mode string defined inside RFC1350. */
  81. #define OPTION_MODE_OCTET "octet" /**< OCTET mode string defined inside RFC1350. */
  82. #define OPTION_BLKSIZE "blksize" /**< Block Size option string defined inside RFC2348. */
  83. #define OPTION_TIMEOUT "timeout" /**< Timeout option string defined inside RFC2349. */
  84. #define OPTION_SIZE "tsize" /**< Transfer Size option string defined inside RFC2348. */
  85. #define NEXT_RETR_MAX_LENGTH 4 /**< Maximum length of TFTP "timeout" option value. */
  86. #define BLKSIZE_MAX_LENGTH 10 /**< Maximum length of TFTP "blksize" option value. */
  87. #define FILE_SIZE_MAX_LENGTH 10 /**< Maximum length of TFTP "tsize" option value. */
  88. #define OPTION_ERROR_MESSAGE "Unsupported option(s) requested"
  89. #define UDP_ERROR_MSG "UDP Error!"
  90. #define LENGTH_ERROR_MSG "Invalid packet length!"
  91. #define UNINT_ERROR_MSG "Connection reset by peer"
  92. #define ACCESS_ERROR_MSG "Access denied (cannot read/write from file)"
  93. #define OPTION_SIZE_REQUEST_VALUE "0"
  94. /**@brief TFTP Error codes. */
  95. #define ERR_UNDEFINED 0 /**< Not defined, see error message (if any). */
  96. #define ERR_FILE_NOT_FOUND 1 /**< File not found. */
  97. #define ERR_ACCESS_ERROR 2 /**< Access violation. */
  98. #define ERR_STORAGE_FULL 3 /**< Disk full or allocation exceeded. */
  99. #define ERR_INVALID_OP 4 /**< Illegal TFTP operation. */
  100. #define ERR_INVALID_TID 5 /**< Unknown transfer ID. */
  101. #define ERR_FILE_EXISTS 6 /**< File already exists. */
  102. #define ERR_BAD_USER 7 /**< No such user. */
  103. #define ERR_OPTION_REJECT 8 /**< Reject proposed options. */
  104. /**@brief TFTP opcode's. This field specifies type of packet. */
  105. #define TYPE_RRQ 1 /**< Read request (RRQ). */
  106. #define TYPE_WRQ 2 /**< Write request (WRQ). */
  107. #define TYPE_DATA 3 /**< Data (DATA). */
  108. #define TYPE_ACK 4 /**< Acknowledgment (ACK). */
  109. #define TYPE_ERR 5 /**< Error (ERROR). */
  110. #define TYPE_OACK 6 /**< Option Acknowledgment (RRQ/WRQ ACK). */
  111. /**
  112. * @defgroup api_param_check API Parameters check macros.
  113. *
  114. * @details Macros that verify parameters passed to the module in the APIs. These macros
  115. * could be mapped to nothing in final versions of code to save execution and size.
  116. * DNS6_DISABLE_API_PARAM_CHECK should be set to 0 to enable these checks.
  117. *
  118. * @{
  119. */
  120. #if (TFTP_DISABLE_API_PARAM_CHECK == 0)
  121. /**@brief Verify NULL parameters are not passed to API by application. */
  122. #define NULL_PARAM_CHECK(PARAM) \
  123. if ((PARAM) == NULL) \
  124. { \
  125. return (NRF_ERROR_NULL | IOT_TFTP_ERR_BASE); \
  126. }
  127. #else // TFTP_DISABLE_API_PARAM_CHECK
  128. #define NULL_PARAM_CHECK(PARAM)
  129. #endif // DNS6_DISABLE_API_PARAM_CHECK
  130. /**@brief Check err_code, free p_buffer and return on error. */
  131. #define PBUFFER_FREE_IF_ERROR(err_code) \
  132. if (err_code != NRF_SUCCESS) \
  133. { \
  134. (void)iot_pbuffer_free(p_buffer, true); \
  135. return err_code; \
  136. }
  137. /**@brief Convert TFTP error code into IOT error with appropriate base. */
  138. #define CONVERT_TO_IOT_ERROR(error_code) \
  139. ((IOT_TFTP_ERR_BASE+0x0040) + NTOHS(error_code))
  140. /**@brief Convert IOT error into TFTP error code by removing TFTP error base. */
  141. #define CONVERT_TO_TFTP_ERROR(error_code) \
  142. (HTONS(err_code - (IOT_TFTP_ERR_BASE+0x0040)))
  143. /**@brief Iterator for string list delimited with '\0'. */
  144. typedef struct
  145. {
  146. char * p_start; /**< Pointer to the beginning of a string. */
  147. char * p_end; /**< Pointer to the end of a string. */
  148. struct curr_struct
  149. {
  150. char * p_key; /**< Pointer to the last, found key string. */
  151. char * p_value; /**< Pointer to the last, found value string. */
  152. } curr;
  153. } option_iter_t;
  154. /**@brief Allowed states of a single TFTP instance. */
  155. typedef enum
  156. {
  157. STATE_FREE = 0, /**< Start state, after calling UDP to allocate socket. */
  158. STATE_IDLE, /**< Socket is allocated, but not used. */
  159. STATE_CONNECTING_RRQ, /**< RRQ packet sent. Waiting for response. */
  160. STATE_CONNECTING_WRQ, /**< WRQ packet sent. Waiting for response. */
  161. STATE_SENDING, /**< Sending file and receiving ACK. */
  162. STATE_SEND_HOLD, /**< Sending held. Waiting for resume call. */
  163. STATE_RECEIVING, /**< Receiving file and sending ACK. */
  164. STATE_RECV_HOLD, /**< Receiving held. Waiting for resume call. */
  165. STATE_RECV_COMPLETE /**< State after receiving last DATA, before sending last ACK packet. There won't be another UDP event to emit IOT_TFTP_EVT_TRANSFER_GET_COMPLETE event, so next resume() should emit that event. */
  166. } tftp_state_t;
  167. /**@brief Internal TFTP instance structure. */
  168. typedef struct
  169. {
  170. iot_tftp_trans_params_t init_params; /**< Connection parameters set during initialization. */
  171. iot_tftp_trans_params_t connect_params; /**< Negotiated Connection parameters. */
  172. udp6_socket_t socket; /**< UDP socket assigned to single instance. */
  173. tftp_state_t state; /**< Integer representing current state of an instance. */
  174. iot_tftp_callback_t callback; /**< User defined callback (passed inside initial parameters structure). */
  175. iot_file_t * p_file; /**< Pointer to destination/source file assigned in get/put call. */
  176. const char * p_path; /**< Path of the file on the remote node. */
  177. uint16_t block_id; /**< ID of last received/sent data block. */
  178. uint16_t src_tid; /**< UDP port used for sending information to the server. */
  179. uint16_t dst_tid; /**< UDP port on which all packets will be sent. At first - dst_port (see below), then reassigned. */
  180. uint16_t dst_port; /**< UDP port on which request packets will be sent. Usually DEFAULT_PORT. */
  181. const char * p_password; /**< Pointer to a constant string containing password passed inside Read/Write Requests. */
  182. ipv6_addr_t addr; /**< IPv6 server address. */
  183. iot_pbuffer_t * p_packet; /**< Reference to the temporary packet buffer. */
  184. uint8_t retries; /**< Number of already performed retries. */
  185. volatile iot_timer_time_in_ms_t request_timeout; /**< Number of milliseconds on which last request should be retransmitted. */
  186. } tftp_instance_t;
  187. SDK_MUTEX_DEFINE(m_tftp_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
  188. static tftp_instance_t m_instances[TFTP_MAX_INSTANCES]; /**< Array of allowed TFTP instances. */
  189. /**@brief Function for finding free TFTP instance index.
  190. *
  191. * @param[out] p_index Index being found.
  192. *
  193. * @retval NRF_SUCCESS if passed instance was found, else NRF_ERROR_NO_MEM error code will
  194. * be returned.
  195. */
  196. static uint32_t find_free_instance(uint32_t * p_index)
  197. {
  198. uint32_t index = 0;
  199. for (index = 0; index < TFTP_MAX_INSTANCES; index++)
  200. {
  201. if (m_instances[index].state == STATE_FREE)
  202. {
  203. *p_index = index;
  204. return NRF_SUCCESS;
  205. }
  206. }
  207. return (NRF_ERROR_NO_MEM | IOT_TFTP_ERR_BASE);
  208. }
  209. /**@brief Function for resolving instance index by passed pointer.
  210. *
  211. * @param[in] p_tftp Pointer representing TFTP instance in user space.
  212. * @param[out] p_index Index of passed TFTP instance.
  213. *
  214. * @retval NRF_SUCCESS if passed instance was found, else NRF_ERROR_INVALID_PARAM error code
  215. * will be returned.
  216. */
  217. static uint32_t find_instance(iot_tftp_t * p_tftp, uint32_t * p_index)
  218. {
  219. if (*p_tftp > TFTP_MAX_INSTANCES)
  220. {
  221. return (NRF_ERROR_INVALID_PARAM | IOT_TFTP_ERR_BASE);
  222. }
  223. *p_index = *p_tftp;
  224. return NRF_SUCCESS;
  225. }
  226. /**@brief Function for notifying application of the TFTP events.
  227. *
  228. * @param[in] p_tftp TFTP instance.
  229. * @param[in] p_evt Event description.
  230. *
  231. * @retval None.
  232. */
  233. static void app_notify(iot_tftp_t * p_tftp, iot_tftp_evt_t * p_evt)
  234. {
  235. uint32_t index;
  236. uint32_t err_code;
  237. err_code = find_instance(p_tftp, &index);
  238. if (err_code != NRF_SUCCESS)
  239. {
  240. return;
  241. }
  242. if (m_instances[index].callback)
  243. {
  244. TFTP_MUTEX_UNLOCK();
  245. // Call handler of user request.
  246. m_instances[index].callback(p_tftp, p_evt);
  247. TFTP_MUTEX_LOCK();
  248. }
  249. }
  250. /**@brief Increment option iterator.
  251. *
  252. * @details The iterator will point to the next option or to p_end if it reaches the end.
  253. *
  254. * @param[in] p_iter Pointer to option iterator.
  255. *
  256. * @retval NRF_SUCCESS if iterator successfully moved to next option, else an error code indicating reason
  257. * for failure.
  258. */
  259. static uint32_t op_get_next(option_iter_t * p_iter)
  260. {
  261. uint32_t key_length;
  262. uint32_t value_length;
  263. NULL_PARAM_CHECK(p_iter->p_start);
  264. NULL_PARAM_CHECK(p_iter->p_end);
  265. NULL_PARAM_CHECK(p_iter->curr.p_key);
  266. NULL_PARAM_CHECK(p_iter->curr.p_value);
  267. // If reached end.
  268. if ((p_iter->curr.p_value == p_iter->p_end) || (p_iter->curr.p_key == p_iter->p_end))
  269. {
  270. return (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE);
  271. }
  272. key_length = strlen(p_iter->curr.p_key);
  273. value_length = strlen(p_iter->curr.p_value);
  274. if ((p_iter->curr.p_value == p_iter->p_start) && (p_iter->curr.p_key == p_iter->p_start))
  275. {
  276. // First call. Check if [start] + [string] fits before [end] reached.
  277. // This statement just checks if there is '\0' between start and end (passing single string as input).
  278. if (p_iter->curr.p_key + key_length < p_iter->p_end)
  279. {
  280. p_iter->curr.p_value = p_iter->curr.p_key + key_length + 1;
  281. return NRF_SUCCESS;
  282. }
  283. else
  284. {
  285. return (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE);
  286. }
  287. }
  288. else if (p_iter->curr.p_value + value_length < p_iter->p_end)
  289. {
  290. p_iter->curr.p_key = p_iter->curr.p_value + value_length + 1;
  291. p_iter->curr.p_value = p_iter->curr.p_key + strlen(p_iter->curr.p_key) + 1;
  292. if ((*p_iter->curr.p_key == '\0') || (*p_iter->curr.p_value == '\0')) // If string list finishes before the end of the buffer.
  293. {
  294. p_iter->curr.p_key = p_iter->p_end;
  295. p_iter->curr.p_value = p_iter->p_end;
  296. return (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE);
  297. }
  298. return NRF_SUCCESS;
  299. }
  300. else
  301. {
  302. p_iter->curr.p_key = p_iter->p_end;
  303. p_iter->curr.p_value = p_iter->p_end;
  304. return (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE);
  305. }
  306. }
  307. /**@brief Set new (key, value) pair at the end of a string.
  308. *
  309. * @param[out] p_iter Pointer to iterator, which will be used to add (key, value) pair.
  310. * @param[in] p_inp_key Pointer to the new key string. If p_key is NULL, then this function will insert just value.
  311. * @param[in] p_inp_value Pointer to the new value string.
  312. *
  313. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  314. * for failure.
  315. */
  316. static __INLINE uint32_t op_set(option_iter_t * p_iter, const char * p_inp_key, const char * p_inp_value)
  317. {
  318. char * p_last_key;
  319. char * p_last_value;
  320. NULL_PARAM_CHECK(p_iter->p_start);
  321. NULL_PARAM_CHECK(p_iter->p_end);
  322. NULL_PARAM_CHECK(p_iter->curr.p_key);
  323. NULL_PARAM_CHECK(p_iter->curr.p_value);
  324. p_last_key = p_iter->curr.p_key;
  325. p_last_value = p_iter->curr.p_value;
  326. // Print appropriate trace log.
  327. if (p_inp_key != NULL)
  328. {
  329. TFTP_TRC("Set option: %s with value: %s.", p_inp_key, p_inp_value);
  330. }
  331. else
  332. {
  333. TFTP_TRC("Set value: %s.", p_inp_value);
  334. }
  335. // Set key & value pointers.
  336. if ((p_iter->curr.p_key == p_iter->p_start) && (p_iter->curr.p_value == p_iter->p_start)) // Start condition.
  337. {
  338. if (p_inp_key != NULL)
  339. {
  340. p_iter->curr.p_value = p_iter->curr.p_key + strlen(p_inp_key) + 1;
  341. }
  342. else
  343. {
  344. p_iter->curr.p_value = p_iter->curr.p_key; // Insert only passed value.
  345. p_iter->curr.p_key = p_iter->curr.p_value + strlen(p_iter->curr.p_value) + 1; // Just assign anything different that p_start and inside buffer.
  346. }
  347. }
  348. else
  349. {
  350. p_iter->curr.p_key = p_iter->curr.p_value + strlen(p_iter->curr.p_value) + 1; // New key starts where last value ends.
  351. if (p_inp_key != NULL)
  352. {
  353. p_iter->curr.p_value = p_iter->curr.p_key + strlen(p_inp_key) + 1; // If key not null - new value starts where new key ends.
  354. }
  355. else
  356. {
  357. p_iter->curr.p_value = p_iter->curr.p_key; // Otherwise - value is placed at the key position.
  358. }
  359. }
  360. // Copy strings into set pointers.
  361. if ((p_iter->curr.p_value + strlen(p_inp_value)) < p_iter->p_end)
  362. {
  363. if (p_inp_key != NULL)
  364. {
  365. memcpy(p_iter->curr.p_key, p_inp_key, strlen(p_inp_key) + 1);
  366. }
  367. memcpy(p_iter->curr.p_value, p_inp_value, strlen(p_inp_value) + 1);
  368. }
  369. else // If it is not possible to insert new key & value pair.
  370. {
  371. p_iter->curr.p_key = p_last_key;
  372. p_iter->curr.p_value = p_last_value;
  373. TFTP_ERR("Unable to set option (size error)!");
  374. return (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE);
  375. }
  376. return NRF_SUCCESS;
  377. }
  378. /**@brief Initializes new option iterator.
  379. *
  380. * @param[out] p_iter Pointer to iterator, which will be configured.
  381. * @param[in] p_buf Pointer to the new string buffer which iterator will be modifying.
  382. * @param[in] buf_len Length of passed buffer.
  383. *
  384. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  385. * for failure.
  386. */
  387. static __INLINE void op_init(option_iter_t * p_iter, char * p_buf, uint32_t buf_len)
  388. {
  389. p_iter->p_start = p_buf;
  390. p_iter->p_end = p_buf + buf_len;
  391. p_iter->curr.p_key = p_buf;
  392. p_iter->curr.p_value = p_buf;
  393. }
  394. /**@brief: Converts string containing unsigned number into uint32_t.
  395. *
  396. * @param[in] p_str Input string.
  397. *
  398. * @retval Integer number equal to read value. Reading process skips all non-digit characters.
  399. */
  400. static uint32_t str_to_uint(char * p_str)
  401. {
  402. uint32_t len;
  403. uint32_t ret_val = 0;
  404. uint32_t mul = 1;
  405. if (p_str == NULL)
  406. {
  407. return 0;
  408. }
  409. len = strlen(p_str);
  410. while (len)
  411. {
  412. len--;
  413. if ((p_str[len] >= '0') && (p_str[len] <= '9')) // Skip unsupported characters.
  414. {
  415. ret_val += mul * (p_str[len] - '0');
  416. mul *= 10;
  417. }
  418. }
  419. return ret_val;
  420. }
  421. /**@brief: Converts unsigned number into string.
  422. *
  423. * @param[in] number Input number.
  424. * @param[out] p_str Pointer to the output string.
  425. * @param[in] len Length of the passed output string buffer.
  426. *
  427. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  428. * for failure.
  429. */
  430. static uint32_t uint_to_str(uint32_t number, char * p_str, uint16_t len)
  431. {
  432. uint32_t i = 0;
  433. uint32_t temp = number;
  434. if (len == 0)
  435. {
  436. return NRF_ERROR_INVALID_LENGTH;
  437. }
  438. // Check how many characters will be needed.
  439. if (temp == 0)
  440. {
  441. i = 1;
  442. }
  443. while (temp)
  444. {
  445. i++;
  446. temp /= 10;
  447. }
  448. // Set null character and check length.
  449. if (i + 1 > len)
  450. {
  451. p_str[0] = '\0';
  452. return NRF_ERROR_INVALID_LENGTH;
  453. }
  454. p_str[i] = '\0';
  455. // Set digits.
  456. while (i--)
  457. {
  458. p_str[i] = '0' + number % 10;
  459. number /= 10;
  460. }
  461. return NRF_SUCCESS;
  462. }
  463. /**@brief Compare strings in a case insensitive way.
  464. *
  465. * @param[in] p_str1 Pointer to the first string.
  466. * @param[in] p_str2 Pointer to the second String.
  467. *
  468. * @retval If strings are equal returns 0, otherwise number of common characters.
  469. */
  470. static uint32_t strcmp_ci(char * p_str1, char* p_str2)
  471. {
  472. uint32_t min_len = 0;
  473. uint32_t str1_len;
  474. uint32_t str2_len;
  475. uint32_t i = 0;
  476. str1_len = strlen(p_str1);
  477. str2_len = strlen(p_str2);
  478. min_len = str1_len;
  479. if (str2_len < str1_len)
  480. {
  481. min_len = str2_len;
  482. }
  483. for (i = 0; i < min_len; i++)
  484. {
  485. char c1 = ((p_str1[i] >= 'a' && p_str1[i] <= 'z') ? p_str1[i] + 'A' - 'a' : p_str1[i]);
  486. char c2 = ((p_str2[i] >= 'a' && p_str2[i] <= 'z') ? p_str2[i] + 'A' - 'a' : p_str2[i]);
  487. if (c1 != c2)
  488. {
  489. return i + 1;
  490. }
  491. }
  492. if (str1_len != str2_len)
  493. {
  494. return i + 1;
  495. }
  496. return 0;
  497. }
  498. /**@brief Allocates p_buffer and fills in common fields.
  499. *
  500. * @param[in] type First field describing packet type.
  501. * @param[in] id Second field (Block ID / Error Code).
  502. * @param[out] pp_buffer Sets pointer to the newly allocated buffer.
  503. * @param[in] payload_len Length of payload (additional fields / data).
  504. *
  505. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  506. * for failure.
  507. */
  508. static uint32_t compose_packet(uint16_t type,
  509. uint16_t id,
  510. iot_pbuffer_t ** pp_buffer,
  511. uint32_t payload_len)
  512. {
  513. uint32_t err_code;
  514. iot_pbuffer_alloc_param_t buffer_param;
  515. iot_pbuffer_t * p_buffer;
  516. uint32_t byte_index;
  517. memset(&buffer_param, 0, sizeof(iot_pbuffer_alloc_param_t));
  518. buffer_param.length = TFTP_HEADER_SIZE + TFTP_BLOCK_ID_SIZE + payload_len;
  519. buffer_param.type = UDP6_PACKET_TYPE;
  520. buffer_param.flags = PBUFFER_FLAG_DEFAULT;
  521. err_code = iot_pbuffer_allocate(&buffer_param, &p_buffer);
  522. if (err_code != NRF_SUCCESS)
  523. {
  524. return err_code;
  525. }
  526. memset(p_buffer->p_payload, 0, buffer_param.length);
  527. byte_index = 0;
  528. // Insert type opcode.
  529. byte_index += uint16_encode(HTONS(type), &p_buffer->p_payload[byte_index]);
  530. if (type == TYPE_ERR)
  531. {
  532. // Insert err code.
  533. byte_index += uint16_encode(CONVERT_TO_TFTP_ERROR(id), &p_buffer->p_payload[byte_index]);
  534. }
  535. else
  536. {
  537. // Insert block ID.
  538. byte_index += uint16_encode(HTONS(id), &p_buffer->p_payload[byte_index]);
  539. }
  540. *pp_buffer = p_buffer;
  541. return NRF_SUCCESS;
  542. }
  543. /**@brief Reset instance request timer.
  544. *
  545. * @param[in] index Index of pending instance.
  546. *
  547. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  548. * for failure.
  549. */
  550. static uint32_t retr_timer_reset(uint32_t index)
  551. {
  552. uint32_t err_code;
  553. iot_timer_time_in_ms_t wall_clock_value;
  554. // Get wall clock time.
  555. err_code = iot_timer_wall_clock_get(&wall_clock_value);
  556. if (err_code == NRF_SUCCESS)
  557. {
  558. m_instances[index].request_timeout = wall_clock_value + m_instances[index].connect_params.next_retr * 1000;
  559. }
  560. return err_code;
  561. }
  562. /**@brief Function for checking if retransmission time of TFTP instance request has been expired.
  563. *
  564. * @param[in] index Index of pending instance.
  565. *
  566. * @retval True if timer has been expired, False otherwise.
  567. */
  568. static bool instance_timer_is_expired(uint32_t index)
  569. {
  570. uint32_t err_code;
  571. iot_timer_time_in_ms_t wall_clock_value;
  572. // Get wall clock time.
  573. err_code = iot_timer_wall_clock_get(&wall_clock_value);
  574. if (err_code == NRF_SUCCESS)
  575. {
  576. if (wall_clock_value >= m_instances[index].request_timeout)
  577. {
  578. return true;
  579. }
  580. }
  581. return false;
  582. }
  583. /**@brief Sets all instance values to defaults. */
  584. static void instance_reset(uint32_t index)
  585. {
  586. m_instances[index].state = STATE_FREE;
  587. m_instances[index].init_params.next_retr = 0;
  588. m_instances[index].init_params.block_size = TFTP_DEFAULT_BLOCK_SIZE;
  589. m_instances[index].connect_params.next_retr = 0;
  590. m_instances[index].connect_params.block_size = TFTP_DEFAULT_BLOCK_SIZE;
  591. m_instances[index].p_file = NULL;
  592. m_instances[index].block_id = 0;
  593. m_instances[index].p_packet = NULL;
  594. m_instances[index].dst_port = TFTP_DEFAULT_PORT;
  595. m_instances[index].dst_tid = TFTP_DEFAULT_PORT;
  596. m_instances[index].retries = 0;
  597. m_instances[index].request_timeout = 0;
  598. m_instances[index].callback = NULL;
  599. m_instances[index].src_tid = 0;
  600. m_instances[index].p_password = NULL;
  601. memset(&m_instances[index].addr, 0, sizeof(ipv6_addr_t));
  602. memset(&m_instances[index].socket, 0, sizeof(udp6_socket_t));
  603. }
  604. /**@brief This function creates error packet for specified TFTP instance.
  605. *
  606. * @param[in] index Index of TFTP instance.
  607. * @param[in] p_err_evt Event data structure (message and code).
  608. *
  609. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  610. * for failure.
  611. */
  612. static uint32_t send_err_msg(uint32_t index, iot_tftp_evt_err_t * p_err_evt)
  613. {
  614. iot_pbuffer_t * p_buffer;
  615. uint8_t * p_resp_packet;
  616. uint32_t msg_len = 0;
  617. uint16_t byte_index = 0;
  618. uint32_t err_code;
  619. TFTP_TRC("Send ERROR packet.");
  620. if (p_err_evt->p_msg != NULL)
  621. {
  622. msg_len = strlen(p_err_evt->p_msg) + 1;
  623. }
  624. err_code = compose_packet(TYPE_ERR, p_err_evt->code, &p_buffer, msg_len);
  625. if (err_code != NRF_SUCCESS)
  626. {
  627. return err_code;
  628. }
  629. p_resp_packet = p_buffer->p_payload;
  630. byte_index = TFTP_HEADER_SIZE + TFTP_ERR_CODE_SIZE;
  631. if (p_err_evt->p_msg != NULL)
  632. {
  633. memcpy(&p_resp_packet[byte_index], p_err_evt->p_msg, msg_len);
  634. byte_index += msg_len;
  635. }
  636. p_buffer->length = byte_index;
  637. TFTP_TRC("Send packet to UDP module.");
  638. UNUSED_VARIABLE(retr_timer_reset(index));
  639. err_code = udp6_socket_sendto(&m_instances[index].socket,
  640. &m_instances[index].addr,
  641. m_instances[index].dst_tid,
  642. p_buffer);
  643. TFTP_TRC("Recv code: %08lx.", err_code);
  644. return err_code;
  645. }
  646. /**@brief This function creeates error packet for TID error, not being found.
  647. *
  648. * @param[in] p_socket Socket from which error message is sent.
  649. * @param[in] p_addr IPv6 Address to where error message is sent.
  650. * @param[in] tid Erronous TID from the sender.
  651. *
  652. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  653. * for failure.
  654. */
  655. static uint32_t send_err_tid(const udp6_socket_t * p_socket, const ipv6_addr_t * p_addr, uint16_t tid)
  656. {
  657. iot_pbuffer_t * p_buffer;
  658. uint32_t msg_len = 0;
  659. uint16_t byte_index = 0;
  660. uint32_t err_code;
  661. TFTP_TRC("Send TID ERROR packet.");
  662. err_code = compose_packet(TYPE_ERR, ERR_INVALID_TID, &p_buffer, msg_len);
  663. if (err_code != NRF_SUCCESS)
  664. {
  665. return err_code;
  666. }
  667. byte_index = TFTP_HEADER_SIZE + TFTP_ERR_CODE_SIZE;
  668. p_buffer->length = byte_index;
  669. TFTP_TRC("Send packet to UDP module.");
  670. err_code = udp6_socket_sendto(p_socket, p_addr, tid, p_buffer);
  671. TFTP_TRC("Recv code: %08lx.", err_code);
  672. return err_code;
  673. }
  674. /**@brief Sends ACK or next data chunk (block) after calling user callback or when hold timer expires.
  675. *
  676. * @param[in] p_tftp Pointer to the TFTP instance (from user space).
  677. * @param[in] p_evt Pointer to the event structure. Used for sending error messages.
  678. *
  679. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  680. * for failure.
  681. */
  682. static uint32_t send_response(iot_tftp_t * p_tftp)
  683. {
  684. uint32_t index;
  685. uint32_t err_code;
  686. TFTP_TRC("Send packet.");
  687. err_code = find_instance(p_tftp, &index);
  688. if (err_code != NRF_SUCCESS)
  689. {
  690. TFTP_ERR("Cannot find instance (send)!");
  691. return err_code;
  692. }
  693. switch (m_instances[index].state)
  694. {
  695. case STATE_IDLE:
  696. // Server should go to the CONNECTING state (request received).
  697. TFTP_TRC("Inside IDLE state (send). ");
  698. return NRF_SUCCESS;
  699. case STATE_SENDING:
  700. case STATE_RECEIVING:
  701. case STATE_SEND_HOLD:
  702. case STATE_RECV_HOLD:
  703. case STATE_RECV_COMPLETE:
  704. // Send DATA/ACK packet.
  705. TFTP_TRC("Send packet to UDP module.");
  706. UNUSED_VARIABLE(retr_timer_reset(index));
  707. err_code = udp6_socket_sendto(&m_instances[index].socket,
  708. &m_instances[index].addr,
  709. m_instances[index].dst_tid,
  710. m_instances[index].p_packet);
  711. TFTP_TRC("Recv code: %08lx.", err_code);
  712. return err_code;
  713. default:
  714. TFTP_ERR("Invalid state (send)!");
  715. return (NRF_ERROR_INVALID_STATE | IOT_TFTP_ERR_BASE);
  716. }
  717. }
  718. /**@brief Aborts TFTP client ongoing procedure.
  719. *
  720. * @param[in] index Index of TFTP instance.
  721. *
  722. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  723. * for failure.
  724. */
  725. void instance_abort(uint32_t index)
  726. {
  727. uint32_t internal_err;
  728. switch (m_instances[index].state)
  729. {
  730. case STATE_SEND_HOLD:
  731. case STATE_RECV_HOLD:
  732. // Free pbuffer.
  733. internal_err = iot_pbuffer_free(m_instances[index].p_packet, true);
  734. if (internal_err != NRF_SUCCESS)
  735. {
  736. TFTP_ERR("Cannot free pbuffer - %p", m_instances[index].p_packet);
  737. }
  738. // Close file.
  739. internal_err = iot_file_fclose(m_instances[index].p_file);
  740. if (internal_err != NRF_SUCCESS)
  741. {
  742. TFTP_ERR("Cannot close file - %p", m_instances[index].p_file);
  743. }
  744. break;
  745. case STATE_SENDING:
  746. case STATE_RECEIVING:
  747. // Close file.
  748. internal_err = iot_file_fclose(m_instances[index].p_file);
  749. if (internal_err != NRF_SUCCESS)
  750. {
  751. TFTP_ERR("Cannot close file - %p", m_instances[index].p_file);
  752. }
  753. break;
  754. case STATE_CONNECTING_RRQ:
  755. case STATE_CONNECTING_WRQ:
  756. case STATE_IDLE:
  757. case STATE_FREE:
  758. default:
  759. break;
  760. }
  761. TFTP_TRC("Reset instance %ld.", index);
  762. m_instances[index].state = STATE_IDLE;
  763. m_instances[index].block_id = 0;
  764. m_instances[index].dst_tid = m_instances[index].dst_port;
  765. m_instances[index].retries = 0;
  766. m_instances[index].request_timeout = 0;
  767. memcpy(&m_instances[index].connect_params,
  768. &m_instances[index].init_params,
  769. sizeof(iot_tftp_trans_params_t));
  770. }
  771. /**@brief Generates event for application.
  772. *
  773. * @param[in] index Index of TFTP instance.
  774. * @param[in] evt_id Id of generated event.
  775. * @param[in] p_param Pointer to event parameter union.
  776. */
  777. static void handle_evt(uint32_t index, iot_tftp_evt_id_t evt_id, iot_tftp_evt_param_t * p_param)
  778. {
  779. uint32_t internal_err;
  780. iot_tftp_evt_t evt;
  781. memset(&evt, 0, sizeof(evt));
  782. evt.id = evt_id;
  783. evt.p_file = m_instances[index].p_file;
  784. if (p_param != NULL)
  785. {
  786. evt.param = * p_param;
  787. }
  788. if (evt_id == IOT_TFTP_EVT_ERROR)
  789. {
  790. uint32_t err_code = evt.param.err.code;
  791. TFTP_TRC("Raise an ERROR event.");
  792. if ((err_code & IOT_TFTP_ERR_BASE) == IOT_TFTP_ERR_BASE)
  793. {
  794. evt.param.err.code = CONVERT_TO_TFTP_ERROR(err_code);
  795. internal_err = send_err_msg(index, &evt.param.err);
  796. if (internal_err != NRF_SUCCESS)
  797. {
  798. TFTP_TRC("Cannot send error message to peer %08lx.", internal_err);
  799. }
  800. }
  801. // Restore error code.
  802. evt.param.err.code = err_code;
  803. // Return to IDLE and notify.
  804. instance_abort(index);
  805. app_notify(&index, &evt);
  806. }
  807. else if ((evt_id == IOT_TFTP_EVT_TRANSFER_GET_COMPLETE) ||
  808. (evt_id == IOT_TFTP_EVT_TRANSFER_PUT_COMPLETE))
  809. {
  810. TFTP_TRC("Raise TRANSFER COMPLETE event.");
  811. if (m_instances[index].state == STATE_RECV_HOLD)
  812. {
  813. TFTP_TRC("Holding last ACK transfer.");
  814. m_instances[index].state = STATE_RECV_COMPLETE;
  815. }
  816. else if (m_instances[index].state != STATE_RECV_COMPLETE)
  817. {
  818. // Skip into IDLE state.
  819. instance_abort(index);
  820. app_notify(&index, &evt);
  821. }
  822. }
  823. else if (evt_id == IOT_TFTP_EVT_TRANSFER_DATA_RECEIVED)
  824. {
  825. app_notify(&index, &evt);
  826. }
  827. }
  828. /**@brief Generates error event for application.
  829. *
  830. * @param[in] index Index of TFTP instance.
  831. * @param[in] err_code Code of error event.
  832. * @param[in] p_msg Character string containing error message.
  833. */
  834. static void handle_evt_err(uint32_t index, uint32_t err_code, char * p_msg)
  835. {
  836. iot_tftp_evt_param_t evt_param;
  837. memset(&evt_param, 0, sizeof(evt_param));
  838. evt_param.err.code = err_code;
  839. evt_param.err.p_msg = p_msg;
  840. evt_param.err.size_transfered = m_instances[index].block_id * m_instances[index].connect_params.block_size;
  841. handle_evt(index, IOT_TFTP_EVT_ERROR, &evt_param);
  842. }
  843. /**@brief: Find instance number by Transmission ID (UDP source port).
  844. *
  845. * @param[in] port UDP port number on which new message was received.
  846. * @param[out] p_index Index of found TFTP instance assigned to the passed UDP port.
  847. *
  848. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  849. * for failure.
  850. */
  851. static __INLINE uint32_t find_instance_by_tid(uint16_t port, uint32_t * p_index)
  852. {
  853. uint32_t index;
  854. for (index = 0; index < TFTP_MAX_INSTANCES; index++)
  855. {
  856. if (m_instances[index].src_tid == port)
  857. {
  858. break;
  859. }
  860. }
  861. if (index == TFTP_MAX_INSTANCES)
  862. {
  863. return (NRF_ERROR_NOT_FOUND | IOT_TFTP_ERR_BASE);
  864. }
  865. *p_index = index;
  866. return NRF_SUCCESS;
  867. }
  868. /**@brief: Negotiation procedure. This function skips through input option string and modifies instance parameters according to negotiated values.
  869. *
  870. * @param[in] p_iter Pointer to iterator configured to parse RQ/OACK packet.
  871. * @param[out] p_instance Pointer to the instance, which parameters should be negotiated.
  872. *
  873. * @retval NRF_SUCCESS on successful execution of procedure, else TFTP_OPTION_REJECT error indicating
  874. * that server/client requests unsupported option values.
  875. */
  876. static uint32_t option_negotiate(option_iter_t * p_iter, tftp_instance_t * p_instance)
  877. {
  878. uint32_t err_code;
  879. bool op_size_set = false;
  880. bool op_blksize_set = false;
  881. bool op_time_set = false;
  882. TFTP_TRC("Negotiate options:");
  883. if (p_iter != NULL) // If NULL passed - reset option values to those defined by RFC.
  884. {
  885. UNUSED_VARIABLE(op_get_next(p_iter));
  886. while (p_iter->curr.p_key != p_iter->p_end)
  887. {
  888. if (strcmp_ci(p_iter->curr.p_key, OPTION_TIMEOUT) == 0)
  889. {
  890. if (p_instance->init_params.next_retr != 0)
  891. {
  892. uint16_t server_time = str_to_uint(p_iter->curr.p_value);
  893. if (server_time < p_instance->init_params.next_retr) // Take minimum.
  894. {
  895. p_instance->connect_params.next_retr = server_time;
  896. }
  897. else
  898. {
  899. p_instance->connect_params.next_retr = p_instance->init_params.next_retr;
  900. }
  901. op_time_set = true;
  902. TFTP_TRC("TIMEOUT: %ld", p_instance->connect_params.next_retr);
  903. }
  904. }
  905. else if (strcmp_ci(p_iter->curr.p_key, OPTION_SIZE) == 0)
  906. {
  907. if (p_instance->p_file != NULL)
  908. {
  909. uint32_t file_size = str_to_uint(p_iter->curr.p_value);
  910. err_code = iot_file_fopen(p_instance->p_file, file_size);
  911. if (err_code != NRF_SUCCESS)
  912. {
  913. TFTP_TRC(" TSIZE: REJECT!");
  914. return TFTP_OPTION_REJECT;
  915. }
  916. op_size_set = true;
  917. TFTP_TRC(" TSIZE: %ld", file_size);
  918. }
  919. }
  920. else if (strcmp_ci(p_iter->curr.p_key, OPTION_BLKSIZE) == 0)
  921. {
  922. uint16_t block_size = str_to_uint(p_iter->curr.p_value);
  923. op_blksize_set = true;
  924. if (p_instance->init_params.block_size >= block_size)
  925. {
  926. p_instance->connect_params.block_size = block_size;
  927. }
  928. else
  929. {
  930. TFTP_TRC("BLKSIZE: REJECT!");
  931. return TFTP_OPTION_REJECT;
  932. }
  933. TFTP_TRC("BLKSIZE: %d", p_instance->connect_params.block_size);
  934. }
  935. else if ((strlen(p_iter->curr.p_key) > 0) && (p_iter->curr.p_value == p_iter->p_end))
  936. {
  937. // Password option.
  938. TFTP_TRC("PASSWORD FOUND: %s", p_iter->curr.p_key);
  939. p_iter->curr.p_key = p_iter->p_end;
  940. }
  941. else
  942. {
  943. TFTP_TRC("UNKNOWN OPTION");
  944. }
  945. UNUSED_VARIABLE(op_get_next(p_iter));
  946. }
  947. }
  948. // Set values of not negotiated options.
  949. if (!op_size_set && p_instance->p_file != NULL)
  950. {
  951. err_code = iot_file_fopen(p_instance->p_file, 0);// Open with default file size (not known).
  952. if (err_code != NRF_SUCCESS)
  953. {
  954. TFTP_TRC("TSIZE: REJECT!");
  955. return TFTP_OPTION_REJECT;
  956. }
  957. TFTP_TRC("TSIZE: %ld", p_instance->p_file->file_size);
  958. }
  959. if (!op_blksize_set)
  960. {
  961. if ((p_instance->init_params.block_size < TFTP_DEFAULT_BLOCK_SIZE) &&
  962. (p_instance->init_params.block_size != 0))
  963. {
  964. TFTP_TRC("BLKSIZE: REJECT!");
  965. return TFTP_OPTION_REJECT;
  966. }
  967. else
  968. {
  969. p_instance->connect_params.block_size = TFTP_DEFAULT_BLOCK_SIZE;
  970. }
  971. TFTP_TRC("BLKSIZE: %d", p_instance->connect_params.block_size);
  972. }
  973. if (!op_time_set)
  974. {
  975. p_instance->connect_params.next_retr = p_instance->init_params.next_retr;
  976. TFTP_TRC("TIMEOUT: %ld", p_instance->connect_params.next_retr);
  977. }
  978. return NRF_SUCCESS;
  979. }
  980. /**@brief This function holds ongoing transmission of TFTP.
  981. *
  982. * @param[in] index Index of TFTP instance.
  983. *
  984. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  985. * for failure.
  986. */
  987. static uint32_t transfer_hold(uint32_t index)
  988. {
  989. if (m_instances[index].state == STATE_SENDING)
  990. {
  991. m_instances[index].state = STATE_SEND_HOLD;
  992. }
  993. else if (m_instances[index].state == STATE_RECEIVING)
  994. {
  995. m_instances[index].state = STATE_RECV_HOLD;
  996. }
  997. else if (m_instances[index].state == STATE_RECV_COMPLETE)
  998. {
  999. m_instances[index].state = STATE_RECV_COMPLETE;
  1000. }
  1001. else
  1002. {
  1003. TFTP_ERR("Hold called in invalid state.");
  1004. return (NRF_ERROR_INVALID_STATE | IOT_TFTP_ERR_BASE);
  1005. }
  1006. return NRF_SUCCESS;
  1007. }
  1008. /**@brief This function resumes ongoing transmission of TFTP.
  1009. *
  1010. * @param[in] index Index of TFTP instance.
  1011. *
  1012. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1013. * for failure.
  1014. */
  1015. static uint32_t transfer_resume(uint32_t index)
  1016. {
  1017. uint32_t err_code = NRF_SUCCESS;
  1018. if ((m_instances[index].state != STATE_SEND_HOLD) &&
  1019. (m_instances[index].state != STATE_RECV_HOLD) &&
  1020. (m_instances[index].state != STATE_RECV_COMPLETE))
  1021. {
  1022. TFTP_ERR("Failed due to invalid state.");
  1023. TFTP_EXIT();
  1024. return (NRF_ERROR_INVALID_STATE | IOT_TFTP_ERR_BASE);
  1025. }
  1026. err_code = send_response(&index);
  1027. if (err_code != NRF_SUCCESS)
  1028. {
  1029. TFTP_ERR("Failed to send packet after resume.");
  1030. }
  1031. if (m_instances[index].state == STATE_SEND_HOLD)
  1032. {
  1033. m_instances[index].state = STATE_SENDING;
  1034. }
  1035. else if (m_instances[index].state == STATE_RECV_HOLD)
  1036. {
  1037. m_instances[index].state = STATE_RECEIVING;
  1038. }
  1039. else if (m_instances[index].state == STATE_RECV_COMPLETE)
  1040. {
  1041. m_instances[index].state = STATE_RECEIVING;
  1042. TFTP_ERR("Complete due to STATE_RECV_COMPLETE state.");
  1043. handle_evt(index, IOT_TFTP_EVT_TRANSFER_GET_COMPLETE, NULL);
  1044. }
  1045. return err_code;
  1046. }
  1047. /**@brief This function creates ACK packet for specified TFTP instance.
  1048. *
  1049. * @param[in] index Index of TFTP instance.
  1050. * @param[in] block_id Data block ID to be acknowledged.
  1051. *
  1052. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1053. * for failure.
  1054. */
  1055. static uint32_t create_ack_packet(uint32_t index, uint16_t block_id)
  1056. {
  1057. uint32_t err_code;
  1058. TFTP_ENTRY();
  1059. // Reuse p_packet pointer for a new (response) packet. Previous one will be automatically freed by IPv6 module.
  1060. err_code = compose_packet(TYPE_ACK,
  1061. block_id,
  1062. &m_instances[index].p_packet,
  1063. 0);
  1064. return err_code;
  1065. }
  1066. /**@brief This function creates data packet for specified TFTP instance.
  1067. *
  1068. * @param[in] index Index of TFTP instance.
  1069. * @param[in] block_id Data block ID to be sent.
  1070. *
  1071. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1072. * for failure.
  1073. */
  1074. static uint32_t create_data_packet(uint32_t index, uint16_t block_id)
  1075. {
  1076. uint32_t err_code;
  1077. uint32_t internal_err;
  1078. uint32_t cursor;
  1079. uint32_t byte_index;
  1080. iot_pbuffer_t * p_buffer = NULL;
  1081. TFTP_ENTRY();
  1082. if (m_instances[index].p_file == NULL)
  1083. {
  1084. TFTP_ERR("[TFTP]: Error while sending response. Reason: Missing file to send.\r\n");
  1085. return NRF_ERROR_INVALID_DATA;
  1086. }
  1087. // If ACK block ID doesn't match last sent packet number.
  1088. if (m_instances[index].block_id != block_id)
  1089. {
  1090. // fseek on file to move to the right point. If fseek returns error - whole transmission will be dropped.
  1091. err_code = iot_file_fseek(m_instances[index].p_file,
  1092. (block_id) * m_instances[index].connect_params.block_size);
  1093. if (err_code != NRF_SUCCESS)
  1094. {
  1095. TFTP_ERR("Unable to fseek on input data file!");
  1096. }
  1097. else
  1098. {
  1099. m_instances[index].block_id = block_id + 1;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. m_instances[index].block_id = block_id + 1;
  1105. }
  1106. cursor = (m_instances[index].block_id - 1) * m_instances[index].connect_params.block_size;
  1107. // If previous DATA packet wasn't fully filled.
  1108. if (cursor > m_instances[index].p_file->file_size)
  1109. {
  1110. TFTP_TRC("Transfer complete. Don't send data.");
  1111. handle_evt(index, IOT_TFTP_EVT_TRANSFER_PUT_COMPLETE, NULL);
  1112. return NRF_SUCCESS;
  1113. }
  1114. else if (cursor + m_instances[index].connect_params.block_size >
  1115. m_instances[index].p_file->file_size) // If current sendto operation will send all remaining data.
  1116. {
  1117. TFTP_TRC("Send last data packet.");
  1118. err_code = compose_packet(TYPE_DATA,
  1119. m_instances[index].block_id,
  1120. &p_buffer,
  1121. m_instances[index].p_file->file_size - cursor);
  1122. }
  1123. else
  1124. {
  1125. TFTP_TRC("Send regular data packet.");
  1126. err_code = compose_packet(TYPE_DATA,
  1127. m_instances[index].block_id,
  1128. &p_buffer,
  1129. m_instances[index].connect_params.block_size);
  1130. }
  1131. if (err_code != NRF_SUCCESS)
  1132. {
  1133. return err_code;
  1134. }
  1135. TFTP_TRC("Created packet:");
  1136. TFTP_TRC("length: %ld", p_buffer->length);
  1137. TFTP_TRC(" type: %d", p_buffer->p_payload[0] * 256 + p_buffer->p_payload[1]);
  1138. TFTP_TRC(" ID: %d", p_buffer->p_payload[2] * 256 + p_buffer->p_payload[3]);
  1139. byte_index = TFTP_HEADER_SIZE + TFTP_BLOCK_ID_SIZE;
  1140. // Save reference to correctly filled packet buffer.
  1141. m_instances[index].p_packet = p_buffer;
  1142. if (p_buffer->length - TFTP_HEADER_SIZE - TFTP_BLOCK_ID_SIZE != 0)
  1143. {
  1144. TFTP_MUTEX_UNLOCK();
  1145. // Hold transfer.
  1146. internal_err = transfer_hold(index);
  1147. if (internal_err != NRF_SUCCESS)
  1148. {
  1149. TFTP_ERR("Error while holding the transfer. Reason: %08lx.", internal_err);
  1150. }
  1151. err_code = iot_file_fread(m_instances[index].p_file,
  1152. &(p_buffer->p_payload[byte_index]),
  1153. p_buffer->length - TFTP_HEADER_SIZE - TFTP_BLOCK_ID_SIZE);
  1154. // Unlock instance if file has not assigned callback (probably no needs more time to perform read/write).
  1155. if (m_instances[index].p_file->p_callback == NULL)
  1156. {
  1157. internal_err = transfer_resume(index);
  1158. if (internal_err != NRF_SUCCESS)
  1159. {
  1160. TFTP_ERR("Error while resuming the transfer. Reason: %08lx.", internal_err);
  1161. }
  1162. }
  1163. TFTP_MUTEX_LOCK();
  1164. }
  1165. else
  1166. {
  1167. // TFTP is going to send empty data packet, so file callback won't be called.
  1168. internal_err = send_response(&index);
  1169. if (internal_err != NRF_SUCCESS)
  1170. {
  1171. TFTP_ERR("Error while sending response. Reason: %08lx.", internal_err);
  1172. }
  1173. }
  1174. if (err_code != NRF_SUCCESS)
  1175. {
  1176. TFTP_ERR("Failed to save received data (fread)!");
  1177. handle_evt_err(index, TFTP_ACCESS_DENIED, ACCESS_ERROR_MSG);
  1178. }
  1179. return err_code;
  1180. }
  1181. /**@brief Callback handler to receive data on the UDP port.
  1182. *
  1183. * @param[in] p_socket Socket identifier.
  1184. * @param[in] p_ip_header IPv6 header containing source and destination addresses.
  1185. * @param[in] p_udp_header UDP header identifying local and remote endpoints.
  1186. * @param[in] process_result Result of data reception, there could be possible errors like
  1187. * invalid checksum etc.
  1188. * @param[in] p_rx_packet Packet buffer containing the received data packet.
  1189. *
  1190. * @retval NRF_SUCCESS Indicates received data was handled successfully, else an an
  1191. * error code indicating reason for failure..
  1192. */
  1193. static uint32_t client_process(const udp6_socket_t * p_socket,
  1194. const ipv6_header_t * p_ip_header,
  1195. const udp6_header_t * p_udp_header,
  1196. uint32_t process_result,
  1197. iot_pbuffer_t * p_rx_packet)
  1198. {
  1199. uint32_t index;
  1200. iot_tftp_evt_t evt;
  1201. uint8_t * p_new_packet;
  1202. uint32_t byte_index;
  1203. uint32_t err_code;
  1204. uint32_t internal_err;
  1205. uint16_t packet_opcode;
  1206. option_iter_t oack_iter;
  1207. uint16_t recv_block_id;
  1208. TFTP_ENTRY();
  1209. TFTP_MUTEX_LOCK();
  1210. err_code = find_instance_by_tid(p_udp_header->destport, &index);
  1211. if (err_code != NRF_SUCCESS)
  1212. {
  1213. TFTP_ERR("Unable to find TFTP instance associated with given UDP port.");
  1214. // Send TID error to the server.
  1215. err_code = send_err_tid(p_socket, &p_ip_header->srcaddr, p_udp_header->destport);
  1216. TFTP_EXIT();
  1217. TFTP_MUTEX_UNLOCK();
  1218. return err_code;
  1219. }
  1220. // Check UDP status code.
  1221. if (process_result != NRF_SUCCESS)
  1222. {
  1223. TFTP_ERR("UDP error!");
  1224. evt.id = IOT_TFTP_EVT_ERROR;
  1225. evt.param.err.code = process_result;
  1226. evt.param.err.p_msg = UDP_ERROR_MSG;
  1227. // Call user callback (inform about error).
  1228. app_notify(&index, &evt);
  1229. TFTP_EXIT();
  1230. TFTP_MUTEX_UNLOCK();
  1231. return process_result;
  1232. }
  1233. // Check packet length.
  1234. if (p_rx_packet->length < TFTP_HEADER_SIZE + TFTP_BLOCK_ID_SIZE)
  1235. {
  1236. TFTP_ERR("Invalid packet length!");
  1237. evt.id = IOT_TFTP_EVT_ERROR;
  1238. evt.param.err.code = TFTP_INVALID_PACKET;
  1239. evt.param.err.p_msg = (char *)"Invalid packet length!";
  1240. app_notify(&index, &evt);
  1241. TFTP_EXIT();
  1242. TFTP_MUTEX_UNLOCK();
  1243. return evt.param.err.code;
  1244. }
  1245. // Read received packet type.
  1246. p_new_packet = p_rx_packet->p_payload;
  1247. packet_opcode = uint16_decode(p_new_packet);
  1248. packet_opcode = NTOHS(packet_opcode);
  1249. byte_index = TFTP_HEADER_SIZE;
  1250. if ((m_instances[index].state == STATE_SEND_HOLD) ||
  1251. (m_instances[index].state == STATE_RECV_HOLD) ||
  1252. (m_instances[index].state == STATE_IDLE))
  1253. {
  1254. TFTP_TRC("Ignore packets in HOLD/IDLE states.");
  1255. TFTP_MUTEX_UNLOCK();
  1256. TFTP_EXIT();
  1257. return NRF_SUCCESS; // Ignore retransmission of other side.
  1258. }
  1259. switch (packet_opcode)
  1260. {
  1261. case TYPE_OACK:
  1262. if ((m_instances[index].state != STATE_CONNECTING_RRQ) &&
  1263. (m_instances[index].state != STATE_CONNECTING_WRQ) &&
  1264. (m_instances[index].state != STATE_IDLE && m_instances[index].retries > 0))
  1265. {
  1266. TFTP_ERR("Invalid TFTP instance state!");
  1267. break;
  1268. }
  1269. op_init(&oack_iter,
  1270. (char *)&p_new_packet[byte_index],
  1271. p_rx_packet->length - TFTP_HEADER_SIZE); // Options uses whole packet except opcode.
  1272. TFTP_TRC("Received OACK.");
  1273. err_code = option_negotiate(&oack_iter, &m_instances[index]);
  1274. if (err_code != NRF_SUCCESS)
  1275. {
  1276. TFTP_ERR("Failed to negotiate options!");
  1277. handle_evt_err(index, TFTP_OPTION_REJECT, OPTION_ERROR_MESSAGE);
  1278. break;
  1279. }
  1280. // Set server transmission id.
  1281. m_instances[index].dst_tid = p_udp_header->srcport;
  1282. if (m_instances[index].state == STATE_CONNECTING_RRQ)
  1283. {
  1284. m_instances[index].p_packet = p_rx_packet;
  1285. m_instances[index].state = STATE_RECEIVING;
  1286. err_code = create_ack_packet(index, 0);
  1287. if (err_code == NRF_SUCCESS)
  1288. {
  1289. err_code = send_response(&index);
  1290. }
  1291. }
  1292. else if (m_instances[index].state == STATE_CONNECTING_WRQ)
  1293. {
  1294. m_instances[index].state = STATE_SENDING;
  1295. err_code = create_data_packet(index, 0);
  1296. }
  1297. else
  1298. {
  1299. TFTP_ERR("Incorrect state to receive OACK!");
  1300. }
  1301. if (err_code != NRF_SUCCESS)
  1302. {
  1303. TFTP_ERR("Failed to create packet!");
  1304. handle_evt_err(index, err_code, NULL);
  1305. }
  1306. break;
  1307. case TYPE_ACK:
  1308. recv_block_id = uint16_decode(&p_new_packet[byte_index]);
  1309. recv_block_id = NTOHS(recv_block_id);
  1310. if (m_instances[index].state == STATE_CONNECTING_WRQ)
  1311. {
  1312. TFTP_TRC("Options not supported. Received ACK.");
  1313. err_code = option_negotiate(NULL, &m_instances[index]);
  1314. if (err_code != NRF_SUCCESS)
  1315. {
  1316. TFTP_ERR("Failed to negotiate default options!");
  1317. handle_evt_err(index, TFTP_OPTION_REJECT, OPTION_ERROR_MESSAGE);
  1318. break;
  1319. }
  1320. // Set server transmission id.
  1321. m_instances[index].dst_tid = p_udp_header->srcport;
  1322. // Set instance state.
  1323. m_instances[index].state = STATE_SENDING;
  1324. m_instances[index].block_id = 0;
  1325. }
  1326. if (m_instances[index].state == STATE_SENDING || m_instances[index].state == STATE_RECEIVING)
  1327. {
  1328. if (recv_block_id == m_instances[index].block_id)
  1329. {
  1330. m_instances[index].retries = 0;
  1331. }
  1332. TFTP_TRC("Received ACK. Send block %4d of %ld.", m_instances[index].block_id + 1,
  1333. CEIL_DIV(m_instances[index].p_file->file_size, m_instances[index].connect_params.block_size) +
  1334. ((m_instances[index].p_file->file_size % m_instances[index].connect_params.block_size == 0) ? 0 : 1));
  1335. err_code = create_data_packet(index, recv_block_id);
  1336. if ((err_code != (NRF_ERROR_DATA_SIZE | IOT_TFTP_ERR_BASE)) && (err_code != NRF_SUCCESS))
  1337. {
  1338. TFTP_ERR("Failed to create data packet.");
  1339. handle_evt_err(index, err_code, NULL);
  1340. }
  1341. }
  1342. else
  1343. {
  1344. TFTP_ERR("Invalid state to receive ACK packet.");
  1345. TFTP_MUTEX_UNLOCK();
  1346. TFTP_EXIT();
  1347. return NRF_SUCCESS;
  1348. }
  1349. break;
  1350. case TYPE_DATA:
  1351. recv_block_id = uint16_decode(&p_new_packet[byte_index]);
  1352. recv_block_id = NTOHS(recv_block_id);
  1353. byte_index += TFTP_BLOCK_ID_SIZE;
  1354. if (m_instances[index].state == STATE_CONNECTING_RRQ)
  1355. {
  1356. TFTP_TRC("Options not supported. Received DATA.");
  1357. err_code = option_negotiate(NULL, &m_instances[index]);
  1358. if (err_code != NRF_SUCCESS)
  1359. {
  1360. TFTP_ERR("Failed to set default options.");
  1361. handle_evt_err(index, TFTP_OPTION_REJECT, OPTION_ERROR_MESSAGE);
  1362. break;
  1363. }
  1364. if (recv_block_id == 1) // Received first data block.
  1365. {
  1366. m_instances[index].block_id = 0;
  1367. m_instances[index].state = STATE_RECEIVING;
  1368. }
  1369. // Set server transmission id.
  1370. m_instances[index].dst_tid = p_udp_header->srcport;
  1371. }
  1372. if (m_instances[index].state == STATE_RECEIVING)
  1373. {
  1374. TFTP_TRC("Received DATA.");
  1375. m_instances[index].p_packet = p_rx_packet;
  1376. if (recv_block_id == m_instances[index].block_id + 1)
  1377. {
  1378. TFTP_TRC("Received next DATA (n+1).");
  1379. m_instances[index].retries = 0;
  1380. err_code = create_ack_packet(index, m_instances[index].block_id + 1);
  1381. if (err_code != NRF_SUCCESS)
  1382. {
  1383. TFTP_ERR("Failed to create ACK packet!");
  1384. handle_evt_err(index, err_code, NULL);
  1385. break;
  1386. }
  1387. }
  1388. else
  1389. {
  1390. TFTP_TRC("Skip current DATA packet. Try to request proper block ID by sending ACK.");
  1391. err_code = create_ack_packet(index, m_instances[index].block_id);
  1392. if (err_code == NRF_SUCCESS)
  1393. {
  1394. err_code = send_response(&index);
  1395. }
  1396. else
  1397. {
  1398. TFTP_ERR("Failed to create ACK packet.");
  1399. handle_evt_err(index, err_code, NULL);
  1400. }
  1401. }
  1402. // Check if payload size is smaller than defined block size.
  1403. if ((p_rx_packet->length - TFTP_BLOCK_ID_SIZE - TFTP_HEADER_SIZE) <
  1404. m_instances[index].connect_params.block_size)
  1405. {
  1406. m_instances[index].state = STATE_RECV_COMPLETE;
  1407. }
  1408. else if (err_code != NRF_SUCCESS)
  1409. {
  1410. TFTP_ERR("Failed to create ACK packet.");
  1411. handle_evt_err(index, err_code, NULL);
  1412. break;
  1413. }
  1414. TFTP_TRC("Send block %4d of %ld ACK.", m_instances[index].block_id,
  1415. m_instances[index].p_file->file_size / m_instances[index].connect_params.block_size);
  1416. if (recv_block_id == m_instances[index].block_id + 1)
  1417. {
  1418. m_instances[index].block_id = recv_block_id;
  1419. TFTP_MUTEX_UNLOCK();
  1420. if (p_rx_packet->length - byte_index > 0)
  1421. {
  1422. iot_tftp_evt_param_t evt_param;
  1423. memset(&evt_param, 0, sizeof(evt_param));
  1424. evt_param.data_received.p_data = &p_new_packet[byte_index];
  1425. evt_param.data_received.size = p_rx_packet->length - byte_index;
  1426. internal_err = transfer_hold(index);
  1427. if (internal_err != NRF_SUCCESS)
  1428. {
  1429. TFTP_ERR("Error while holding the transfer. Reason: %08lx.", internal_err);
  1430. }
  1431. if (m_instances[index].p_file != NULL)
  1432. {
  1433. err_code = iot_file_fwrite(m_instances[index].p_file,
  1434. evt_param.data_received.p_data,
  1435. evt_param.data_received.size);
  1436. }
  1437. handle_evt(index, IOT_TFTP_EVT_TRANSFER_DATA_RECEIVED, &evt_param);
  1438. // Unlock instance if file has not assigned callback (probably not needs more time to perform read/write).
  1439. if (m_instances[index].p_file == NULL || m_instances[index].p_file->p_callback == NULL)
  1440. {
  1441. internal_err = transfer_resume(index);
  1442. if (internal_err != NRF_SUCCESS)
  1443. {
  1444. TFTP_ERR("Error while resuming the transfer. Reason: %08lx.", internal_err);
  1445. }
  1446. }
  1447. }
  1448. else
  1449. {
  1450. if (m_instances[index].p_file != NULL)
  1451. {
  1452. err_code = iot_file_fclose(m_instances[index].p_file);
  1453. }
  1454. internal_err = send_response(&index);
  1455. if (internal_err != NRF_SUCCESS)
  1456. {
  1457. TFTP_ERR("Error while sending response. Reason: %08lx.", internal_err);
  1458. }
  1459. TFTP_ERR("Complete due to packet length. (%ld: %ld)", p_rx_packet->length, byte_index);
  1460. m_instances[index].state = STATE_RECEIVING;
  1461. handle_evt(index, IOT_TFTP_EVT_TRANSFER_GET_COMPLETE, NULL);
  1462. }
  1463. TFTP_MUTEX_LOCK();
  1464. if (err_code != NRF_SUCCESS)
  1465. {
  1466. TFTP_ERR("Failed to save received data (fwrite)!");
  1467. handle_evt_err(index, TFTP_ACCESS_DENIED, ACCESS_ERROR_MSG);
  1468. break;
  1469. }
  1470. }
  1471. }
  1472. else
  1473. {
  1474. TFTP_ERR("Invalid state to receive DATA packet.");
  1475. TFTP_MUTEX_UNLOCK();
  1476. TFTP_EXIT();
  1477. return NRF_SUCCESS;
  1478. }
  1479. break;
  1480. case TYPE_ERR:
  1481. recv_block_id = uint16_decode(&p_new_packet[byte_index]);
  1482. recv_block_id = NTOHS(recv_block_id);
  1483. byte_index += TFTP_ERR_CODE_SIZE;
  1484. TFTP_ERR("Received error packet!");
  1485. evt.id = IOT_TFTP_EVT_ERROR;
  1486. evt.param.err.code = CONVERT_TO_IOT_ERROR(recv_block_id);
  1487. if (p_rx_packet->length > TFTP_HEADER_SIZE + TFTP_ERR_CODE_SIZE)
  1488. {
  1489. evt.param.err.p_msg = (char *) &p_new_packet[byte_index];
  1490. p_new_packet[p_rx_packet->length-1] = '\0';
  1491. }
  1492. app_notify(&index, &evt);
  1493. TFTP_MUTEX_UNLOCK();
  1494. TFTP_EXIT();
  1495. if (evt.param.err.code != TFTP_INVALID_TID)
  1496. {
  1497. instance_abort(index);
  1498. }
  1499. return evt.param.err.code;
  1500. default:
  1501. TFTP_ERR("Invalid TFTP packet opcode!");
  1502. handle_evt_err(index, TFTP_INVALID_PACKET, NULL);
  1503. break;
  1504. }
  1505. TFTP_EXIT();
  1506. return err_code;
  1507. }
  1508. /**@brief Count how many bytes are required to store options inside request packet.
  1509. *
  1510. * @param[in] index Index of TFTP instance.
  1511. * @param[in] type Type of TFTP request.
  1512. *
  1513. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1514. * for failure.
  1515. */
  1516. static uint32_t count_options_length(uint32_t index, uint32_t type)
  1517. {
  1518. uint32_t op_length = 0;
  1519. char next_retr_str[NEXT_RETR_MAX_LENGTH];
  1520. char block_size_str[BLKSIZE_MAX_LENGTH];
  1521. char file_size_str[FILE_SIZE_MAX_LENGTH];
  1522. if ((m_instances[index].init_params.next_retr > 0) &&
  1523. (m_instances[index].init_params.next_retr < 256))
  1524. {
  1525. UNUSED_VARIABLE(uint_to_str(m_instances[index].init_params.next_retr, next_retr_str, NEXT_RETR_MAX_LENGTH));
  1526. op_length += sizeof(OPTION_TIMEOUT); // Time out option length.
  1527. op_length += strlen(next_retr_str) + 1; // The '\0' character ate the end of a string.
  1528. }
  1529. if ((m_instances[index].init_params.block_size > 0) &&
  1530. (m_instances[index].init_params.block_size != TFTP_DEFAULT_BLOCK_SIZE))
  1531. {
  1532. UNUSED_VARIABLE(uint_to_str(m_instances[index].init_params.block_size, block_size_str, sizeof(block_size_str)));
  1533. op_length += sizeof(OPTION_BLKSIZE); // Time out option length.
  1534. op_length += strlen(block_size_str) + 1; // The '\0' character ate the end of a string.
  1535. }
  1536. op_length += sizeof(OPTION_SIZE); // TFTP tsize option length.
  1537. if (type == TYPE_RRQ)
  1538. {
  1539. op_length += sizeof(OPTION_SIZE_REQUEST_VALUE); // Just send 0 to inform other side that you support this option and would like to receive file size inside OptionACK.
  1540. }
  1541. if (type == TYPE_WRQ)
  1542. {
  1543. UNUSED_VARIABLE(uint_to_str(m_instances[index].p_file->file_size, file_size_str, sizeof(file_size_str)));
  1544. op_length += strlen(file_size_str) + 1;
  1545. }
  1546. if (m_instances[index].p_password != NULL)
  1547. {
  1548. if (m_instances[index].p_password[0] != '\0')
  1549. {
  1550. op_length += strlen(m_instances[index].p_password) + 1; // Password is always sent as last string without option name.
  1551. }
  1552. }
  1553. return op_length;
  1554. }
  1555. /**@brief This function inserts options into request packet payload using passed option iterator.
  1556. *
  1557. * @param[in] index Index of TFTP instance.
  1558. * @param[in] type Type of TFTP request.
  1559. * @param[in] p_iter Iterator which will be used to set options.
  1560. *
  1561. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1562. * for failure.
  1563. */
  1564. static uint32_t insert_options(uint32_t index, uint32_t type, option_iter_t * p_iter)
  1565. {
  1566. uint32_t err_code = NRF_SUCCESS;
  1567. char next_retr_str[NEXT_RETR_MAX_LENGTH];
  1568. char block_size_str[BLKSIZE_MAX_LENGTH];
  1569. char file_size_str[FILE_SIZE_MAX_LENGTH];
  1570. if (type == TYPE_RRQ)
  1571. {
  1572. err_code = op_set(p_iter, OPTION_SIZE, OPTION_SIZE_REQUEST_VALUE);
  1573. }
  1574. if (type == TYPE_WRQ)
  1575. {
  1576. UNUSED_VARIABLE(uint_to_str(m_instances[index].p_file->file_size, file_size_str, FILE_SIZE_MAX_LENGTH));
  1577. err_code = op_set(p_iter, OPTION_SIZE, file_size_str);
  1578. }
  1579. if (err_code == NRF_SUCCESS)
  1580. {
  1581. if ((m_instances[index].init_params.next_retr > 0) &&
  1582. (m_instances[index].init_params.next_retr < 256))
  1583. {
  1584. UNUSED_VARIABLE(uint_to_str(m_instances[index].init_params.next_retr, next_retr_str, NEXT_RETR_MAX_LENGTH));
  1585. err_code = op_set(p_iter, OPTION_TIMEOUT, next_retr_str);
  1586. if (err_code != NRF_SUCCESS)
  1587. {
  1588. return err_code;
  1589. }
  1590. }
  1591. if ((m_instances[index].init_params.block_size > 0) &&
  1592. (m_instances[index].init_params.block_size != TFTP_DEFAULT_BLOCK_SIZE))
  1593. {
  1594. UNUSED_VARIABLE(uint_to_str(m_instances[index].init_params.block_size, block_size_str, BLKSIZE_MAX_LENGTH));
  1595. err_code = op_set(p_iter, OPTION_BLKSIZE, block_size_str);
  1596. if (err_code != NRF_SUCCESS)
  1597. {
  1598. return err_code;
  1599. }
  1600. }
  1601. if (m_instances[index].p_password != NULL)
  1602. {
  1603. if (m_instances[index].p_password[0] != '\0')
  1604. {
  1605. err_code = op_set(p_iter, NULL, m_instances[index].p_password);
  1606. }
  1607. }
  1608. }
  1609. return err_code;
  1610. }
  1611. /**@Sends Read/Write TFTP Request.
  1612. *
  1613. * @param[in] type Type of request (allowed values: TYPE_RRQ and TYPE_WRQ).
  1614. * @param[in] p_tftp Pointer to the TFTP instance (from user space).
  1615. * @param[in] p_file Pointer to the file, which should be assigned to passed instance.
  1616. * @param[in] p_params Pointer to transmission parameters structure (retransmission time, block size).
  1617. *
  1618. * @retval NRF_SUCCESS on successful execution of procedure, else an error code indicating reason
  1619. * for failure.
  1620. */
  1621. static uint32_t send_request(uint32_t type,
  1622. iot_tftp_t * p_tftp,
  1623. iot_file_t * p_file,
  1624. const char * p_path)
  1625. {
  1626. uint32_t err_code;
  1627. iot_pbuffer_t * p_buffer;
  1628. iot_pbuffer_alloc_param_t buffer_param;
  1629. uint8_t * p_rrq_packet;
  1630. option_iter_t rrq_iter;
  1631. uint32_t index;
  1632. uint32_t byte_index;
  1633. err_code = find_instance(p_tftp, &index);
  1634. if (err_code != NRF_SUCCESS)
  1635. {
  1636. return err_code;
  1637. }
  1638. if (p_path == NULL || p_path[0] == '\0')
  1639. {
  1640. TFTP_ERR("[TFTP]: Invalid path passed.\r\n");
  1641. return (NRF_ERROR_INVALID_PARAM | IOT_TFTP_ERR_BASE);
  1642. }
  1643. if (p_file != NULL && p_file->p_filename[0] == '\0')
  1644. {
  1645. TFTP_ERR("Invalid file name passed!");
  1646. return (NRF_ERROR_INVALID_PARAM | IOT_TFTP_ERR_BASE);
  1647. }
  1648. if (m_instances[index].state != STATE_IDLE)
  1649. {
  1650. TFTP_ERR("Invalid instance state!");
  1651. return (NRF_ERROR_INVALID_STATE | IOT_TFTP_ERR_BASE);
  1652. }
  1653. // Assign file with TFTP instance.
  1654. m_instances[index].p_file = p_file;
  1655. m_instances[index].p_path = p_path;
  1656. m_instances[index].block_id = 0;
  1657. m_instances[index].dst_tid = m_instances[index].dst_port;
  1658. memset(&buffer_param, 0, sizeof(buffer_param));
  1659. buffer_param.type = UDP6_PACKET_TYPE;
  1660. buffer_param.flags = PBUFFER_FLAG_DEFAULT;
  1661. // Calculate size of required packet.
  1662. buffer_param.length = TFTP_HEADER_SIZE; // Bytes reserved for TFTP opcode value.
  1663. buffer_param.length += strlen(p_path) + 1; // File name with '\0' character.
  1664. buffer_param.length += sizeof(OPTION_MODE_OCTET); // Mode option value length.
  1665. TFTP_TRC("Estimated packet length without options: %ld.", buffer_param.length);
  1666. buffer_param.length += count_options_length(index, type); // TFTP options.
  1667. TFTP_TRC("Estimated packet length with options: %ld.", buffer_param.length);
  1668. // Allocate packet buffer.
  1669. err_code = iot_pbuffer_allocate(&buffer_param, &p_buffer);
  1670. if (err_code != NRF_SUCCESS)
  1671. {
  1672. return err_code;
  1673. }
  1674. memset(p_buffer->p_payload, 0, buffer_param.length);
  1675. byte_index = 0;
  1676. // Compose TFTP Read Request according to configuration.
  1677. p_rrq_packet = p_buffer->p_payload;
  1678. uint16_t size = uint16_encode(HTONS(type), &p_rrq_packet[byte_index]);
  1679. byte_index += size;
  1680. // Initialization of option iterator.
  1681. op_init(&rrq_iter, (char *)&p_rrq_packet[byte_index], buffer_param.length - TFTP_HEADER_SIZE); // Options uses whole packet except opcode.
  1682. rrq_iter.p_start[0] = '\0';
  1683. // Insert file path and mode strings.
  1684. err_code = op_set(&rrq_iter, NULL, p_path);
  1685. PBUFFER_FREE_IF_ERROR(err_code);
  1686. err_code = op_set(&rrq_iter, NULL, OPTION_MODE_OCTET);
  1687. PBUFFER_FREE_IF_ERROR(err_code);
  1688. // Insert TFTP options into packet.
  1689. err_code = insert_options(index, type, &rrq_iter);
  1690. PBUFFER_FREE_IF_ERROR(err_code);
  1691. // Change instance status to connecting.
  1692. if (type == TYPE_RRQ)
  1693. {
  1694. m_instances[index].state = STATE_CONNECTING_RRQ;
  1695. }
  1696. else
  1697. {
  1698. m_instances[index].state = STATE_CONNECTING_WRQ;
  1699. }
  1700. // Send read request.
  1701. UNUSED_VARIABLE(retr_timer_reset(index));
  1702. err_code = udp6_socket_sendto(&m_instances[index].socket,
  1703. &m_instances[index].addr,
  1704. m_instances[index].dst_tid,
  1705. p_buffer);
  1706. if (err_code != NRF_SUCCESS)
  1707. {
  1708. TFTP_ERR("Unable to send request!");
  1709. m_instances[index].state = STATE_IDLE;
  1710. }
  1711. PBUFFER_FREE_IF_ERROR(err_code);
  1712. return NRF_SUCCESS;
  1713. }
  1714. /**@brief Function used in order to change initial connection parameters. */
  1715. uint32_t iot_tftp_set_params(iot_tftp_t * p_tftp, iot_tftp_trans_params_t * p_params)
  1716. {
  1717. uint32_t err_code;
  1718. uint32_t index;
  1719. NULL_PARAM_CHECK(p_params);
  1720. NULL_PARAM_CHECK(p_tftp);
  1721. TFTP_ENTRY();
  1722. TFTP_MUTEX_LOCK();
  1723. err_code = find_instance(p_tftp, &index);
  1724. if (err_code == NRF_SUCCESS)
  1725. {
  1726. // Modifying connection parameters could be done only when TFTP instance is disconnected.
  1727. // NOTE: STATE_FREE is not allowed, because there have to be a moment (e.g. after calling iot_tftp_init()) when transmission parameters were set to default values.
  1728. if (m_instances[index].state == STATE_IDLE)
  1729. {
  1730. // Reset connection parameters to initial values. They will be set (negotiated) after get/put call.
  1731. memcpy(&m_instances[index].init_params, p_params, sizeof(iot_tftp_trans_params_t));
  1732. }
  1733. else
  1734. {
  1735. err_code = (NRF_ERROR_INVALID_STATE | IOT_TFTP_ERR_BASE);
  1736. TFTP_ERR("Cannot modify connection parameters inside %d state!", m_instances[index].state);
  1737. }
  1738. }
  1739. else
  1740. {
  1741. TFTP_ERR("Unable to find TFTP instance!");
  1742. }
  1743. TFTP_MUTEX_UNLOCK();
  1744. TFTP_EXIT();
  1745. return err_code;
  1746. }
  1747. /**@brief Function for performing retransmissions of TFTP acknowledgments. */
  1748. void iot_tftp_timeout_process(iot_timer_time_in_ms_t wall_clock_value)
  1749. {
  1750. uint32_t index;
  1751. uint32_t err_code;
  1752. UNUSED_PARAMETER(wall_clock_value);
  1753. TFTP_MUTEX_LOCK();
  1754. for (index = 0; index < TFTP_MAX_INSTANCES; index++)
  1755. {
  1756. if ((m_instances[index].state == STATE_CONNECTING_RRQ) ||
  1757. (m_instances[index].state == STATE_CONNECTING_WRQ) ||
  1758. (m_instances[index].state == STATE_SENDING) ||
  1759. (m_instances[index].state == STATE_RECEIVING))
  1760. {
  1761. TFTP_ENTRY();
  1762. TFTP_TRC("Current timer: %ld, %ld", m_instances[index].request_timeout, wall_clock_value);
  1763. if (instance_timer_is_expired(index))
  1764. {
  1765. err_code = NRF_SUCCESS;
  1766. if (m_instances[index].retries < TFTP_MAX_RETRANSMISSION_COUNT)
  1767. {
  1768. TFTP_TRC("Query retransmission [%d] for file %s.",
  1769. m_instances[index].retries, m_instances[index].p_file->p_filename);
  1770. // Increase retransmission number.
  1771. m_instances[index].retries++;
  1772. TFTP_TRC("Compose packet for retransmission.");
  1773. // Send packet again.
  1774. if (m_instances[index].state == STATE_RECEIVING)
  1775. {
  1776. TFTP_TRC("Retransmission of ACK packet.");
  1777. err_code = create_ack_packet(index, m_instances[index].block_id);
  1778. if (err_code == NRF_SUCCESS)
  1779. {
  1780. err_code = send_response(&index);
  1781. }
  1782. else
  1783. {
  1784. TFTP_ERR("Failed to create packet!");
  1785. handle_evt_err(index, err_code, NULL);
  1786. }
  1787. }
  1788. else if (m_instances[index].state == STATE_SENDING)
  1789. {
  1790. TFTP_TRC("Retransmission of DATA packet.");
  1791. err_code = create_data_packet(index, m_instances[index].block_id - 1);
  1792. if (err_code == NRF_SUCCESS)
  1793. {
  1794. if (m_instances[index].p_file->p_callback == NULL)
  1795. {
  1796. err_code = send_response(&index);
  1797. }
  1798. }
  1799. else
  1800. {
  1801. TFTP_ERR("Failed to create packet!");
  1802. handle_evt_err(index, err_code, NULL);
  1803. }
  1804. }
  1805. else if (m_instances[index].state == STATE_CONNECTING_RRQ)
  1806. {
  1807. TFTP_TRC("OACK time out. Retransmit RRQ.");
  1808. m_instances[index].state = STATE_IDLE;
  1809. err_code = send_request(TYPE_RRQ, &index, m_instances[index].p_file, m_instances[index].p_path);
  1810. }
  1811. else if (m_instances[index].state == STATE_CONNECTING_WRQ)
  1812. {
  1813. TFTP_TRC("OACK time out. Retransmit WRQ.");
  1814. m_instances[index].state = STATE_IDLE;
  1815. err_code = send_request(TYPE_WRQ, &index, m_instances[index].p_file, NULL);
  1816. }
  1817. else
  1818. {
  1819. TFTP_TRC("In idle state.");
  1820. }
  1821. }
  1822. else
  1823. {
  1824. TFTP_ERR("TFTP server did not response on query for file %s.",
  1825. m_instances[index].p_file->p_filename);
  1826. // No response from server.
  1827. err_code = TFTP_REMOTE_UNREACHABLE;
  1828. }
  1829. if (err_code != NRF_SUCCESS)
  1830. {
  1831. // Inform application that timeout occurs.
  1832. TFTP_ERR("Timeout error.");
  1833. handle_evt_err(index, err_code, NULL);
  1834. }
  1835. }
  1836. TFTP_MUTEX_UNLOCK();
  1837. TFTP_EXIT();
  1838. return;
  1839. }
  1840. }
  1841. TFTP_MUTEX_UNLOCK();
  1842. }
  1843. /**@brief Initializes TFTP client. */
  1844. uint32_t iot_tftp_init(iot_tftp_t * p_tftp, iot_tftp_init_t * p_init_params)
  1845. {
  1846. uint32_t index = 0;
  1847. uint32_t err_code;
  1848. NULL_PARAM_CHECK(p_tftp);
  1849. NULL_PARAM_CHECK(p_init_params);
  1850. NULL_PARAM_CHECK(p_init_params->p_ipv6_addr);
  1851. TFTP_ENTRY();
  1852. TFTP_MUTEX_LOCK();
  1853. // Find first available instance.
  1854. err_code = find_free_instance(&index);
  1855. if (err_code == NRF_SUCCESS)
  1856. {
  1857. // Reset instance values.
  1858. instance_reset(index);
  1859. // Assign new values.
  1860. *p_tftp = index;
  1861. m_instances[index].callback = p_init_params->callback;
  1862. m_instances[index].src_tid = p_init_params->src_port;
  1863. m_instances[index].dst_port = p_init_params->dst_port;
  1864. m_instances[index].p_password = p_init_params->p_password;
  1865. m_instances[index].dst_tid = m_instances[index].dst_port;
  1866. memcpy(&m_instances[index].addr, p_init_params->p_ipv6_addr, sizeof(ipv6_addr_t));
  1867. // Configure socket.
  1868. err_code = udp6_socket_allocate(&m_instances[index].socket);
  1869. if (err_code == NRF_SUCCESS)
  1870. {
  1871. err_code = udp6_socket_bind(&m_instances[index].socket,
  1872. IPV6_ADDR_ANY,
  1873. p_init_params->src_port);
  1874. if (err_code == NRF_SUCCESS)
  1875. {
  1876. // Attach callback.
  1877. err_code = udp6_socket_recv(&m_instances[index].socket, client_process);
  1878. if (err_code == NRF_SUCCESS)
  1879. {
  1880. m_instances[index].state = STATE_IDLE;
  1881. }
  1882. }
  1883. if (err_code != NRF_SUCCESS)
  1884. {
  1885. (void)udp6_socket_free(&m_instances[index].socket);
  1886. TFTP_ERR("UDP socket configuration failure!");
  1887. }
  1888. }
  1889. }
  1890. else
  1891. {
  1892. TFTP_ERR("No more free instances left!");
  1893. }
  1894. TFTP_MUTEX_UNLOCK();
  1895. TFTP_EXIT();
  1896. return err_code;
  1897. }
  1898. /**@brief Resets TFTP client instance, so it is possible to make another request after error. */
  1899. uint32_t iot_tftp_abort(iot_tftp_t * p_tftp)
  1900. {
  1901. uint32_t err_code;
  1902. uint32_t index;
  1903. NULL_PARAM_CHECK(p_tftp);
  1904. TFTP_ENTRY();
  1905. TFTP_MUTEX_LOCK();
  1906. err_code = find_instance(p_tftp, &index);
  1907. if (err_code == NRF_SUCCESS)
  1908. {
  1909. instance_abort(index);
  1910. }
  1911. TFTP_MUTEX_UNLOCK();
  1912. TFTP_EXIT();
  1913. return err_code;
  1914. }
  1915. /**@brief Frees assigned sockets. */
  1916. uint32_t iot_tftp_uninit(iot_tftp_t * p_tftp)
  1917. {
  1918. uint32_t err_code;
  1919. uint32_t index;
  1920. NULL_PARAM_CHECK(p_tftp);
  1921. TFTP_ENTRY();
  1922. TFTP_MUTEX_LOCK();
  1923. err_code = find_instance(p_tftp, &index);
  1924. if (err_code == NRF_SUCCESS)
  1925. {
  1926. if (m_instances[index].state == STATE_SEND_HOLD ||
  1927. m_instances[index].state == STATE_RECV_HOLD ||
  1928. m_instances[index].state == STATE_SENDING ||
  1929. m_instances[index].state == STATE_RECEIVING)
  1930. {
  1931. // Free pbuffer.
  1932. err_code = iot_pbuffer_free(m_instances[index].p_packet, true);
  1933. if (err_code != NRF_SUCCESS)
  1934. {
  1935. TFTP_ERR("Cannot free pbuffer - %p", m_instances[index].p_packet);
  1936. }
  1937. err_code = iot_file_fclose(m_instances[index].p_file);
  1938. if (err_code != NRF_SUCCESS)
  1939. {
  1940. TFTP_ERR("Cannot close file - %p", m_instances[index].p_file);
  1941. }
  1942. }
  1943. if (m_instances[index].state != STATE_IDLE)
  1944. {
  1945. handle_evt_err(index, TFTP_UNDEFINED_ERROR, UNINT_ERROR_MSG);
  1946. }
  1947. (void)udp6_socket_free(&m_instances[index].socket);
  1948. m_instances[index].state = STATE_FREE;
  1949. }
  1950. TFTP_MUTEX_UNLOCK();
  1951. TFTP_EXIT();
  1952. return err_code;
  1953. }
  1954. /**@brief Retrieves file from remote server into p_file. */
  1955. uint32_t iot_tftp_get(iot_tftp_t * p_tftp, iot_file_t * p_file, const char * p_path)
  1956. {
  1957. uint32_t err_code;
  1958. NULL_PARAM_CHECK(p_tftp);
  1959. NULL_PARAM_CHECK(p_path);
  1960. if (p_file != NULL)
  1961. {
  1962. NULL_PARAM_CHECK(p_file->p_filename);
  1963. }
  1964. TFTP_ENTRY();
  1965. TFTP_MUTEX_LOCK();
  1966. err_code = send_request(TYPE_RRQ, p_tftp, p_file, p_path);
  1967. if (err_code != NRF_SUCCESS)
  1968. {
  1969. TFTP_ERR("Error while sending read request. Reason: %08lx.", err_code);
  1970. }
  1971. TFTP_MUTEX_UNLOCK();
  1972. TFTP_EXIT();
  1973. return err_code;
  1974. }
  1975. /**@brief Sends local file p_file to a remote server. */
  1976. uint32_t iot_tftp_put(iot_tftp_t * p_tftp, iot_file_t * p_file, const char * p_path)
  1977. {
  1978. uint32_t err_code;
  1979. NULL_PARAM_CHECK(p_tftp);
  1980. NULL_PARAM_CHECK(p_file);
  1981. NULL_PARAM_CHECK(p_file->p_filename);
  1982. TFTP_ENTRY();
  1983. TFTP_MUTEX_LOCK();
  1984. err_code = send_request(TYPE_WRQ, p_tftp, p_file, p_path);
  1985. if (err_code != NRF_SUCCESS)
  1986. {
  1987. TFTP_ERR("Error while sending write request. Reason: %08lx.", err_code);
  1988. }
  1989. TFTP_MUTEX_UNLOCK();
  1990. TFTP_EXIT();
  1991. return err_code;
  1992. }
  1993. /**@brief Holds transmission of ACK (use in order to slow transmission). */
  1994. uint32_t iot_tftp_hold(iot_tftp_t * p_tftp)
  1995. {
  1996. uint32_t index;
  1997. uint32_t err_code;
  1998. NULL_PARAM_CHECK(p_tftp);
  1999. TFTP_ENTRY();
  2000. TFTP_MUTEX_LOCK();
  2001. err_code = find_instance(p_tftp, &index);
  2002. if (err_code == NRF_SUCCESS)
  2003. {
  2004. // Hold transfer.
  2005. err_code = transfer_hold(index);
  2006. }
  2007. else
  2008. {
  2009. TFTP_ERR("Hold called on unknown TFTP instance.");
  2010. }
  2011. TFTP_MUTEX_UNLOCK();
  2012. TFTP_EXIT();
  2013. return err_code;
  2014. }
  2015. /**@brief Resumes transmission. */
  2016. uint32_t iot_tftp_resume(iot_tftp_t * p_tftp)
  2017. {
  2018. uint32_t index;
  2019. uint32_t err_code;
  2020. NULL_PARAM_CHECK(p_tftp);
  2021. TFTP_ENTRY();
  2022. TFTP_MUTEX_LOCK();
  2023. err_code = find_instance(p_tftp, &index);
  2024. if (err_code == NRF_SUCCESS)
  2025. {
  2026. err_code = transfer_resume(index);
  2027. }
  2028. else
  2029. {
  2030. TFTP_ERR("Failed to find instance.");
  2031. }
  2032. TFTP_MUTEX_UNLOCK();
  2033. TFTP_EXIT();
  2034. return err_code;
  2035. }