[RFC PATCH 5/5] lwip: implement wget command from http_client.c example
Maxim Uvarov
maxim.uvarov at linaro.org
Fri May 5 12:25:29 CEST 2023
Intend of RFC is to show how we can reuse existance lwip apps
and examples inside u-boot. This commit shows how to do that with
minimal changes.
Signed-off-by: Maxim Uvarov <maxim.uvarov at linaro.org>
---
.gitignore | 2 +
doc/README.lwip | 34 ++++++++++++++++
lib/lwip/Makefile | 8 ++++
lib/lwip/apps/http/lwip-wget.c | 67 +++++++++++++++++++++++++++++++
lib/lwip/apps/http/rmstatic.patch | 47 ++++++++++++++++++++++
lib/lwip/cmd-lwip.c | 31 ++++++++++++++
6 files changed, 189 insertions(+)
create mode 100644 lib/lwip/apps/http/lwip-wget.c
create mode 100644 lib/lwip/apps/http/rmstatic.patch
diff --git a/.gitignore b/.gitignore
index aeaf847543..339692f5a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,3 +107,5 @@ __pycache__
/lib/lwip/lwip-external
lib/lwip/apps/ping/ping.c
+lib/lwip/apps/http/http_client.c
+lib/lwip/apps/http/http_client.h
diff --git a/doc/README.lwip b/doc/README.lwip
index df3462ca1b..b59a1568b4 100644
--- a/doc/README.lwip
+++ b/doc/README.lwip
@@ -54,3 +54,37 @@ Unmodified ping example can be used. I did ping from qemu/u-boot tap device on t
ping: recv 3 ms
tcpdump on the host:
5:09:10.925951 ARP, Request who-has 192.168.1.200 tell 192.168.1.200, length 28 15:09:12.114643 IP6 fe80::38e2:41ff:fec3:8bda > ip6-allrouters: ICMP6, router solicitation, length 16 15:09:20.370725 ARP, Request who-has 192.168.1.2 tell 192.168.1.200, length 28 15:09:20.370740 ARP, Reply 192.168.1.2 is-at 3a:e2:41:c3:8b:da (oui Unknown), length 28 15:09:20.372789 IP 192.168.1.200 > 192.168.1.2: ICMP echo request, id 44975, seq 1, length 40 15:09:20.372810 IP 192.168.1.2 > 192.168.1.200: ICMP echo reply, id 44975, seq 1, length 40 15:09:25.426636 ARP, Request who-has 192.168.1.200 tell 192.168.1.2, length 28 15:09:25.426870 ARP, Reply 192.168.1.200 is-at f6:11:01:02:03:04 (oui Unknown), length 28
+
+
+5. Wget example
+
+Http server has 192.168.1.2 IP address. (I did not port DNS resolving yet,
+but it's also exist in lwip.) So example just downloads some file with http
+protocol:
+
+Net: eth0: virtio-net#30
+Hit any key to stop autoboot: 0
+=> lwip init
+Starting lwIP, local interface IP is 192.168.1.200
+Initialized LWIP stack
+=> lwip wget http://192.168.1.2/
+downloading http://192.168.1.2/ to addr 0x40200000
+downloaded chunk size 294, to addr 0x40200000
+downloaded chunk size 318, to addr 0x40200126
+=> md 0x40200000 0x40
+40200000: 4f44213c 50595443 74682045 0a3e6c6d <!DOCTYPE html>.
+40200010: 6d74683c 3c0a3e6c 64616568 743c0a3e <html>.<head>.<t
+40200020: 656c7469 6c65573e 656d6f63 206f7420 itle>Welcome to
+40200030: 6e69676e 2f3c2178 6c746974 3c0a3e65 nginx!</title>.<
+40200040: 6c797473 200a3e65 62202020 2079646f style>. body
+40200050: 20200a7b 20202020 69772020 3a687464 {. width:
+40200060: 65353320 200a3b6d 20202020 6d202020 35em;. m
+40200070: 69677261 30203a6e 74756120 200a3b6f argin: 0 auto;.
+40200080: 20202020 66202020 2d746e6f 696d6166 font-fami
+40200090: 203a796c 6f686154 202c616d 64726556 ly: Tahoma, Verd
+402000a0: 2c616e61 69724120 202c6c61 736e6173 ana, Arial, sans
+402000b0: 7265732d 0a3b6669 20202020 2f3c0a7d -serif;. }.</
+402000c0: 6c797473 3c0a3e65 6165682f 3c0a3e64 style>.</head>.<
+402000d0: 79646f62 683c0a3e 65573e31 6d6f636c body>.<h1>Welcom
+402000e0: 6f742065 69676e20 3c21786e 3e31682f e to nginx!</h1>
+402000f0: 3e703c0a 79206649 7320756f 74206565 .<p>If you see t
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
index 2c665dcb88..e28cfd726e 100644
--- a/lib/lwip/Makefile
+++ b/lib/lwip/Makefile
@@ -75,4 +75,12 @@ $(obj)/apps/ping/ping.c:
obj-$(CONFIG_CMD_LWIP) += apps/ping/ping.o
obj-$(CONFIG_CMD_LWIP) += apps/ping/lwip_ping.o
+$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c
+$(obj)/apps/http/http_client.c:
+ cp ./lib/lwip/lwip-external/src/apps/http/http_client.c $(obj)/apps/http/http_client.c
+ cp ./lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/apps/http/http_client.h
+ patch -p0 < $(obj)/apps/http/rmstatic.patch
+
+obj-y += apps/http/http_client.o
+obj-y += apps/http/lwip-wget.o
diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c
new file mode 100644
index 0000000000..f3295d67f1
--- /dev/null
+++ b/lib/lwip/apps/http/lwip-wget.c
@@ -0,0 +1,67 @@
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include "http_client.h"
+
+extern err_t
+httpc_init_connection(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name,
+ u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg);
+extern err_t
+httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr);
+extern err_t
+httpc_free_state(httpc_state_t* req);
+
+static ulong daddr;
+static httpc_connection_t settings;
+
+static err_t
+httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+ struct pbuf* q;
+ LWIP_UNUSED_ARG(err);
+
+ if (p == NULL) {
+ printf("httpc_tcp_recv bug!\n");
+ return ERR_BUF;
+ }
+
+ for (q = p; q != NULL; q = q->next) {
+ memcpy(daddr, q->payload, q->len);
+ printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr);
+ daddr += q->len;
+ }
+ altcp_recved(pcb, p->tot_len);
+ pbuf_free(p);
+ return ERR_OK;
+}
+
+int lwip_wget(ulong addr, char *url)
+{
+ httpc_state_t* req;
+ err_t err;
+ int port = 80;
+ ip4_addr_t server_addr;
+ char *server_name;
+
+ daddr = addr;
+ IP4_ADDR(&server_addr, 192,168,1,2);
+ server_name = ipaddr_ntoa(&server_addr);
+
+ memset(&settings, 0, sizeof(httpc_connection_t));
+ err = httpc_init_connection(&req, &settings, server_name, port,
+ url, httpc_recv, NULL /*&addr*/);
+ if (err != ERR_OK) {
+ printf("httpc_init_connection failed\n");
+ return err;
+ }
+
+ err = httpc_get_internal_addr(req, &server_addr);
+ if (err != ERR_OK) {
+ httpc_free_state(req);
+ printf("error httpc_get_internal_addr\n");
+ return err;
+ }
+
+ return 0;
+}
diff --git a/lib/lwip/apps/http/rmstatic.patch b/lib/lwip/apps/http/rmstatic.patch
new file mode 100644
index 0000000000..547236de52
--- /dev/null
+++ b/lib/lwip/apps/http/rmstatic.patch
@@ -0,0 +1,47 @@
+--- ./lib/lwip/lwip-external/src/apps/http/http_client.c 2023-05-03 15:26:42.038088829 +0000
++++ lib/lwip/apps/http/http_client.c 2023-05-03 15:27:25.298151160 +0000
+@@ -45,7 +48,7 @@
+ * - IPv6 support
+ */
+
+-#include "lwip/apps/http_client.h"
++#include "http_client.h"
+
+ #include "lwip/altcp_tcp.h"
+ #include "lwip/dns.h"
+@@ -153,7 +156,7 @@ typedef struct _httpc_state
+ } httpc_state_t;
+
+ /** Free http client state and deallocate all resources within */
+-static err_t
++/*static*/ err_t
+ httpc_free_state(httpc_state_t* req)
+ {
+ struct altcp_pcb* tpcb;
+@@ -415,7 +418,7 @@ httpc_tcp_connected(void *arg, struct al
+ }
+
+ /** Start the http request when the server IP addr is known */
+-static err_t
++/*static*/ err_t
+ httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr)
+ {
+ err_t err;
+@@ -592,7 +595,7 @@ httpc_init_connection_common(httpc_state
+ /**
+ * Initialize the connection struct
+ */
+-static err_t
++/* static */ err_t
+ httpc_init_connection(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name,
+ u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg)
+ {
+@@ -786,7 +789,7 @@ httpc_fs_result(void *arg, httpc_result_
+ }
+
+ /** tcp recv callback */
+-static err_t
++/*static*/ err_t
+ httpc_fs_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
+ {
+ httpc_filestate_t *filestate = (httpc_filestate_t*)arg;
diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c
index f2e25a8c29..797f0f2fe2 100644
--- a/lib/lwip/cmd-lwip.c
+++ b/lib/lwip/cmd-lwip.c
@@ -10,6 +10,7 @@
#include <display_options.h>
#include <memalign.h>
#include <net.h>
+#include <image.h>
#include "apps/ping/lwip_ping.h"
@@ -57,10 +58,39 @@ static int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_SUCCESS;
}
+extern int lwip_wget(ulong addr, char *url);
+
+static int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *url;
+
+ if (argc < 2) {
+ printf("argc = %d, error\n", argc);
+ return CMD_RET_USAGE;
+ }
+
+ url = argv[1];
+ printf("downloading %s to addr 0x%lx\n", url, image_load_addr);
+
+ eth_init(); /* activate u-boot eth dev */
+
+ lwip_wget(image_load_addr, url);
+
+ lwip_loop_set();
+ if (net_loop(LWIP) < 0) {
+ printf("wget failed\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
static struct cmd_tbl cmds[] = {
U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "", ""),
U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, "", ""),
U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, "", ""),
+ U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""),
};
static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -88,6 +118,7 @@ U_BOOT_CMD(
"info - display info\n"
"init - init LWIP\n"
"ping addr - ping addr\n"
+ "wget http://192.168.1.2/ \n"
);
/* Old command kept for compatibility. Same as 'mmc info' */
--
2.30.2
More information about the U-Boot
mailing list