tftp_client.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-02-26 tyx first implementation
  9. */
  10. #include <stdio.h>
  11. #include <stdint.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <sys/time.h>
  15. #include <sys/socket.h>
  16. #include <sys/select.h>
  17. #include "tftp_xfer.h"
  18. #include "tftp.h"
  19. struct tftp_client_private
  20. {
  21. struct tftp_xfer *xfer;
  22. fd_set fdr;
  23. struct timeval timeout;
  24. };
  25. extern void *tftp_file_open(const char *fname, const char *mode, int is_write);
  26. extern int tftp_file_write(void *handle, int pos, void *buff, int len);
  27. extern int tftp_file_read(void *handle, int pos, void *buff, int len);
  28. extern void tftp_file_close(void *handle);
  29. extern int tftp_thread_create(void **task, void (*entry)(void *param), void *param);
  30. static int tftp_client_select(struct tftp_client_private *_private)
  31. {
  32. int ret;
  33. FD_ZERO(&_private->fdr);
  34. FD_SET(_private->xfer->sock, &_private->fdr);
  35. _private->timeout.tv_sec = 5;
  36. _private->timeout.tv_usec = 0;
  37. ret = select(_private->xfer->sock + 1, &_private->fdr, NULL, NULL, (void *)&_private->timeout);
  38. if (ret == 0)
  39. {
  40. return -TFTP_ETIMEOUT;
  41. }
  42. else if (ret < 0)
  43. {
  44. return -TFTP_ESYS;
  45. }
  46. return ret;
  47. }
  48. struct tftp_client *tftp_client_create(const char *ip_addr, int port)
  49. {
  50. struct tftp_client_private *_private;
  51. struct tftp_client *client;
  52. /* malloc client mem */
  53. client = malloc(sizeof(struct tftp_client) + sizeof(struct tftp_client_private));
  54. if (client == NULL)
  55. {
  56. tftp_printf("create client failed!! exit \n");
  57. return NULL;
  58. }
  59. /* Creating Private Data */
  60. _private = (struct tftp_client_private *)&client[1];
  61. /* Create a client connection */
  62. _private->xfer = tftp_xfer_create(ip_addr, port);
  63. if (_private->xfer == NULL)
  64. {
  65. tftp_printf("tftp xfer create failed!! exit\n");
  66. free(client);
  67. return NULL;
  68. }
  69. /* Number of Initial Retries */
  70. client->max_retry = TFTP_MAX_RETRY;
  71. /* Initialization error number */
  72. client->err = TFTP_OK;
  73. /* Binding Private Data */
  74. client->_private = _private;
  75. return client;
  76. }
  77. void tftp_client_destroy(struct tftp_client *client)
  78. {
  79. struct tftp_client_private *_private;
  80. if (client == NULL)
  81. {
  82. return;
  83. }
  84. _private = client->_private;
  85. /* Release connection objects */
  86. if (_private && _private->xfer)
  87. {
  88. tftp_xfer_destroy(_private->xfer);
  89. }
  90. /* Free memory */
  91. free(client);
  92. }
  93. int tftp_client_push(struct tftp_client *client, const char *local_name, const char *remote_name)
  94. {
  95. struct tftp_client_private *_private;
  96. void *fp;
  97. struct tftp_packet *pack;
  98. int send_size, r_size;
  99. int file_size = 0;
  100. int res;
  101. int max_retry;
  102. _private = client->_private;
  103. max_retry = client->max_retry;
  104. client->err = TFTP_OK;
  105. while (max_retry)
  106. {
  107. /* Send Write Request */
  108. res = tftp_send_request(_private->xfer, TFTP_CMD_WRQ, remote_name);
  109. if (res != TFTP_OK)
  110. {
  111. tftp_printf("tftp send request failed !! retry:%d. exit\n", client->max_retry - max_retry);
  112. max_retry = 0;
  113. client->err = res;
  114. break;
  115. }
  116. /* Waiting for server response */
  117. res = tftp_client_select(_private);
  118. if (res > 0 && FD_ISSET(_private->xfer->sock, &_private->fdr))
  119. {
  120. /* Receive the server response */
  121. break;
  122. }
  123. else if (res == -TFTP_ETIMEOUT)
  124. {
  125. tftp_printf("tftp wait response timeout. retry\n");
  126. max_retry --;
  127. continue;
  128. }
  129. else
  130. {
  131. /* Waiting for Response Error */
  132. tftp_printf("tftp wait response err:%d. exit\n", res);
  133. max_retry = 0;
  134. client->err = res;
  135. break;
  136. }
  137. }
  138. if (max_retry == 0)
  139. {
  140. return res;
  141. }
  142. /* Receiving ACK */
  143. res = tftp_wait_ack(_private->xfer);
  144. if (res != TFTP_OK)
  145. {
  146. tftp_printf("wait ack failed!! exit\n");
  147. client->err = res;
  148. return res;
  149. }
  150. /* Open file */
  151. fp = tftp_file_open(local_name, _private->xfer->mode, 0);
  152. if (fp == NULL)
  153. {
  154. tftp_printf("open file \"%s\" error.\n", local_name);
  155. client->err = -TFTP_EFILE;
  156. return -TFTP_EFILE;
  157. }
  158. pack = malloc(sizeof(struct tftp_packet));
  159. if (pack == NULL)
  160. {
  161. tftp_transfer_err(_private->xfer, 0, "malloc pack failed!");
  162. tftp_file_close(fp);
  163. client->err = -TFTP_EMEM;
  164. return -TFTP_EMEM;
  165. }
  166. while (1)
  167. {
  168. /* read file */
  169. r_size = tftp_file_read(fp, file_size, &pack->data, _private->xfer->blksize);
  170. if (r_size < 0)
  171. {
  172. max_retry = 0;
  173. client->err = -TFTP_EFILE;
  174. break;
  175. }
  176. max_retry = client->max_retry;
  177. while (max_retry)
  178. {
  179. /* Send data to server */
  180. send_size = tftp_write_data(_private->xfer, pack, r_size + 4);
  181. if (send_size != (r_size + 4))
  182. {
  183. tftp_transfer_err(_private->xfer, 0, "send file err!");
  184. max_retry = 0;
  185. client->err = -TFTP_EDATA;
  186. break;
  187. }
  188. /* Wait server ACK */
  189. res = tftp_client_select(_private);
  190. if (res > 0 && FD_ISSET(_private->xfer->sock, &_private->fdr))
  191. {
  192. /* Receive a server ACK */
  193. break;
  194. }
  195. else if (res == -TFTP_ETIMEOUT)
  196. {
  197. tftp_printf("tftp wait response timeout. retry\n");
  198. max_retry --;
  199. continue;
  200. }
  201. else
  202. {
  203. tftp_printf("tftp wait response err:%d. exit\n", res);
  204. max_retry = 0;
  205. client->err = res;
  206. break;
  207. }
  208. }
  209. if (max_retry == 0)
  210. {
  211. break;
  212. }
  213. /* Receiving ACK */
  214. if (tftp_wait_ack(_private->xfer) != TFTP_OK)
  215. {
  216. tftp_printf("wait ack failed!! exit\n");
  217. client->err = -TFTP_EACK;
  218. break;
  219. }
  220. file_size += r_size;
  221. if (r_size < _private->xfer->blksize)
  222. {
  223. break;
  224. }
  225. }
  226. /* close file */
  227. tftp_file_close(fp);
  228. free(pack);
  229. return file_size;
  230. }
  231. int tftp_client_pull(struct tftp_client *client, const char *remote_name, const char *local_name)
  232. {
  233. struct tftp_client_private *_private;
  234. void *fp;
  235. struct tftp_packet *pack;
  236. int recv_size, w_size;
  237. int file_size = 0;
  238. int res;
  239. int max_retry;
  240. _private = client->_private;
  241. max_retry = client->max_retry;
  242. client->err = TFTP_OK;
  243. while (max_retry)
  244. {
  245. /* Send Read File Request */
  246. res = tftp_send_request(_private->xfer, TFTP_CMD_RRQ, remote_name);
  247. if (res != TFTP_OK)
  248. {
  249. tftp_printf("tftp send request failed !! retry:%d. exit\n", max_retry);
  250. max_retry = 0;
  251. client->err = res;
  252. break;
  253. }
  254. /* Waiting for the server to respond to the request */
  255. res = tftp_client_select(_private);
  256. if (res > 0 && FD_ISSET(_private->xfer->sock, &_private->fdr))
  257. {
  258. /* Receive the server response */
  259. break;
  260. }
  261. else if (res == -TFTP_ETIMEOUT)
  262. {
  263. tftp_printf("tftp wait response timeout. retry\n");
  264. max_retry --;
  265. continue;
  266. }
  267. else
  268. {
  269. tftp_printf("tftp wait response err:%d. exit\n", res);
  270. max_retry = 0;
  271. client->err = res;
  272. break;
  273. }
  274. }
  275. /* More than the maximum number of retries. exit */
  276. if (max_retry == 0)
  277. {
  278. return res;
  279. }
  280. /* Request successful. open file */
  281. fp = tftp_file_open(local_name, _private->xfer->mode, 1);
  282. if (fp == NULL)
  283. {
  284. tftp_printf("open file \"%s\" error.\n", local_name);
  285. client->err = -TFTP_EFILE;
  286. return -TFTP_EFILE;
  287. }
  288. pack = malloc(sizeof(struct tftp_packet));
  289. if (pack == NULL)
  290. {
  291. /* malloc failed. send err msg and exit */
  292. tftp_transfer_err(_private->xfer, 0, "malloc pack failed!");
  293. tftp_file_close(fp);
  294. client->err = -TFTP_EMEM;
  295. return -TFTP_EMEM;
  296. }
  297. while (1)
  298. {
  299. /* Receiving data from server */
  300. recv_size = tftp_read_data(_private->xfer, pack, \
  301. (int)((uint8_t *)&pack->data - (uint8_t *)pack) + _private->xfer->blksize);
  302. if (recv_size < 0)
  303. {
  304. tftp_printf("read data err[%d]! exit\n", recv_size);
  305. client->err = -TFTP_EDATA;
  306. break;
  307. }
  308. /* Write data to file */
  309. w_size = tftp_file_write(fp, file_size, &pack->data, recv_size);
  310. if (w_size != recv_size)
  311. {
  312. tftp_printf("write file err! exit\n");
  313. tftp_transfer_err(_private->xfer, 0, "write file err!");
  314. client->err = -TFTP_EFILE;
  315. break;
  316. }
  317. file_size += recv_size;
  318. /* Data less than one package. Completion of reception */
  319. if (recv_size < _private->xfer->blksize)
  320. {
  321. tftp_resp_ack(_private->xfer);
  322. break;
  323. }
  324. max_retry = client->max_retry;
  325. while (max_retry)
  326. {
  327. /* Send a response signal */
  328. tftp_resp_ack(_private->xfer);
  329. /* Waiting for the server to send data */
  330. res = tftp_client_select(_private);
  331. if (res > 0 && FD_ISSET(_private->xfer->sock, &_private->fdr))
  332. {
  333. break;
  334. }
  335. else if (res == -TFTP_ETIMEOUT)
  336. {
  337. tftp_printf("tftp wait response timeout. retry\n");
  338. max_retry --;
  339. }
  340. else
  341. {
  342. tftp_printf("tftp wait response err:%d. exit\n", res);
  343. max_retry = 0;
  344. client->err = res;
  345. break;
  346. }
  347. }
  348. if (max_retry == 0)
  349. {
  350. break;
  351. }
  352. }
  353. /* close file */
  354. tftp_file_close(fp);
  355. free(pack);
  356. return file_size;
  357. }
  358. int tftp_client_err(struct tftp_client *client)
  359. {
  360. return client->err;
  361. }