1 /*
2  * Copyright (c) 2023 Kickmaker
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_MODULE_NAME net_tftp_client_app
8 #define LOG_LEVEL LOG_LEVEL_DBG
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12 
13 #include <zephyr/net/tftp.h>
14 
15 #define APP_BANNER		"Run TFTP client"
16 #define TFTP_SAMPLE_DATA	"Lorem ipsum dolor sit amet, consectetur adipiscing elit"
17 
18 static struct tftpc client;
19 
tftp_event_callback(const struct tftp_evt * evt)20 static void tftp_event_callback(const struct tftp_evt *evt)
21 {
22 	switch (evt->type) {
23 	case TFTP_EVT_DATA:
24 		LOG_HEXDUMP_INF(evt->param.data.data_ptr,
25 				evt->param.data.len,
26 				"Received data: ");
27 		break;
28 	case TFTP_EVT_ERROR:
29 		LOG_ERR("Error code %d msg: %s",
30 			evt->param.error.code,
31 			evt->param.error.msg);
32 	default:
33 		break;
34 	}
35 }
36 
tftp_init(const char * hostname)37 static int tftp_init(const char *hostname)
38 {
39 	struct sockaddr remote_addr;
40 	struct addrinfo *res, hints = {0};
41 	int ret;
42 
43 	/* Setup TFTP server address */
44 	hints.ai_socktype = SOCK_DGRAM;
45 
46 	ret = getaddrinfo(hostname, CONFIG_TFTP_APP_PORT, &hints, &res);
47 	if (ret != 0) {
48 		LOG_ERR("Unable to resolve address");
49 		/* DNS error codes don't align with normal errors */
50 		return -ENOENT;
51 	}
52 
53 	memcpy(&remote_addr, res->ai_addr, sizeof(remote_addr));
54 	freeaddrinfo(res);
55 
56 	/* Save sockaddr into TFTP client handler */
57 	memcpy(&client.server, &remote_addr, sizeof(client.server));
58 	/* Register TFTP client callback */
59 	client.callback = tftp_event_callback;
60 
61 	return 0;
62 }
63 
main(void)64 int main(void)
65 {
66 	int ret;
67 
68 	LOG_INF(APP_BANNER);
69 
70 	ret = tftp_init(CONFIG_TFTP_APP_SERVER);
71 	if (ret < 0) {
72 		LOG_ERR("Unable to initialize TFTP client");
73 		return ret;
74 	}
75 
76 	/* Get file1.bin in octet mode */
77 	ret = tftp_get(&client, "file1.bin", "octet");
78 	if (ret < 0) {
79 		LOG_ERR("Error while getting file (%d)", ret);
80 		return ret;
81 	}
82 
83 	LOG_INF("TFTP client get done");
84 
85 	/* Put TFTP sample data into newfile.bin to server in octet mode */
86 	ret = tftp_put(&client, "newfile.bin", "octet",
87 			TFTP_SAMPLE_DATA, sizeof(TFTP_SAMPLE_DATA));
88 	if (ret < 0 || ret != sizeof(TFTP_SAMPLE_DATA)) {
89 		LOG_ERR("Error while putting file (%d)", ret);
90 		return ret;
91 	}
92 
93 	LOG_INF("TFTP client put done");
94 
95 	return 0;
96 }
97