[RFC 05/12] WIP: fs/tftp.c: convert to picotcp
Antony Pavlov
antonynpavlov at gmail.com
Wed Jul 15 13:13:43 PDT 2015
Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
fs/tftp.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 175 insertions(+), 24 deletions(-)
diff --git a/fs/tftp.c b/fs/tftp.c
index 0de215e..9d003b4 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -33,6 +33,10 @@
#include <kfifo.h>
#include <linux/sizes.h>
+#include <pico_socket.h>
+#include <pico_ipv4.h>
+#include <poller.h>
+
#define TFTP_PORT 69 /* Well known TFTP port number */
/* Seconds to wait before remote server is allowed to resend a lost packet */
@@ -84,10 +88,17 @@ struct file_priv {
void *buf;
int blocksize;
int block_requested;
+
+ struct pico_socket *sock;
+ union pico_address remote_address;
+ uint16_t remote_port;
+ uint8_t *pkt;
};
struct tftp_priv {
IPaddr_t server;
+
+ union pico_address pserver;
};
static int tftp_create(struct device_d *dev, const char *pathname, mode_t mode)
@@ -120,9 +131,15 @@ static int tftp_send(struct file_priv *priv)
unsigned char *xp;
int len = 0;
uint16_t *s;
- unsigned char *pkt = net_udp_get_payload(priv->tftp_con);
+ uint8_t *pkt;
int ret;
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ pkt = net_udp_get_payload(priv->tftp_con);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pkt = priv->pkt;
+ }
+
debug("%s: state %d\n", __func__, priv->state);
switch (priv->state) {
@@ -169,7 +186,13 @@ static int tftp_send(struct file_priv *priv)
break;
}
- ret = net_udp_send(priv->tftp_con, len);
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ ret = net_udp_send(priv->tftp_con, len);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ /* FIXME: convert PICOTCP error code to barebox error code */
+ ret = pico_socket_sendto(priv->sock, priv->pkt, len,
+ &priv->remote_address, priv->remote_port);
+ }
return ret;
}
@@ -177,9 +200,15 @@ static int tftp_send(struct file_priv *priv)
static int tftp_send_write(struct file_priv *priv, void *buf, int len)
{
uint16_t *s;
- unsigned char *pkt = net_udp_get_payload(priv->tftp_con);
+ uint8_t *pkt;
int ret;
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ pkt = net_udp_get_payload(priv->tftp_con);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pkt = priv->pkt;
+ }
+
s = (uint16_t *)pkt;
*s++ = htons(TFTP_DATA);
*s++ = htons(priv->block);
@@ -188,7 +217,14 @@ static int tftp_send_write(struct file_priv *priv, void *buf, int len)
priv->state = STATE_LAST;
len += 4;
- ret = net_udp_send(priv->tftp_con, len);
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ ret = net_udp_send(priv->tftp_con, len);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ /* FIXME: convert PICOTCP error code to barebox error code */
+ ret = pico_socket_sendto(priv->sock, priv->pkt, len,
+ &priv->remote_address, priv->remote_port);
+ }
+
priv->last_block = priv->block;
priv->state = STATE_WAITACK;
@@ -216,7 +252,12 @@ static int tftp_poll(struct file_priv *priv)
return -ETIMEDOUT;
}
- net_poll();
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ net_poll();
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ /* despite of is_timeout() can call poller_call() by itself ... */
+ poller_call();
+ }
return 0;
}
@@ -293,14 +334,24 @@ static void tftp_recv(struct file_priv *priv,
priv->state = STATE_DONE;
break;
}
- priv->tftp_con->udp->uh_dport = uh_sport;
+
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ priv->remote_port = uh_sport;
+ }
+
priv->state = STATE_WDATA;
break;
case TFTP_OACK:
tftp_parse_oack(priv, pkt, len);
- priv->server_port = ntohs(uh_sport);
- priv->tftp_con->udp->uh_dport = uh_sport;
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ priv->server_port = ntohs(uh_sport);
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ priv->remote_port = uh_sport;
+ }
if (priv->push) {
/* send first block */
@@ -321,8 +372,12 @@ static void tftp_recv(struct file_priv *priv,
if (priv->state == STATE_RRQ || priv->state == STATE_OACK) {
/* first block received */
priv->state = STATE_RDATA;
- priv->tftp_con->udp->uh_dport = uh_sport;
- priv->server_port = ntohs(uh_sport);
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ priv->server_port = ntohs(uh_sport);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ priv->remote_port = uh_sport;
+ }
priv->last_block = 0;
if (priv->block != 1) { /* Assertion */
@@ -381,6 +436,53 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
tftp_recv(priv, pkt, net_eth_to_udplen(packet), udp->uh_sport);
}
+static void tftp_cb(uint16_t ev, struct pico_socket *sock)
+{
+ struct file_priv *priv = sock->priv;
+
+ union pico_address ep;
+ uint16_t remote_port;
+ uint8_t *pkt = priv->pkt;
+ int len;
+
+ if (ev == PICO_SOCK_EV_ERR) {
+ printf(" >>>>>> PICO_SOCK_EV_ERR <<<<<<< \n");
+ return;
+ }
+
+ /*
+ * we have to receive:
+ * opcode (2 bytes)
+ * block# (2 bytes)
+ * data (blocksize bytes)
+ */
+ len = pico_socket_recvfrom(sock, pkt, priv->blocksize + 4,
+ &ep, &remote_port);
+
+ tftp_recv(priv, pkt, len, remote_port);
+}
+
+static struct pico_socket *tftp_socket_open(uint16_t localport)
+{
+ struct pico_socket *sock;
+ union pico_address local_address;
+
+ sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, tftp_cb);
+ if (!sock)
+ return NULL;
+
+ localport = short_be(localport);
+
+ /* FIXME: use local_address == PICO_IPV4_INADDR_ANY */
+ memset(&local_address, 0, sizeof(union pico_address));
+ if (pico_socket_bind(sock, &local_address, &localport) < 0) {
+ pico_socket_close(sock);
+ return NULL;
+ }
+
+ return sock;
+}
+
static struct file_priv *tftp_do_open(struct device_d *dev,
int accmode, const char *filename)
{
@@ -426,17 +528,39 @@ static struct file_priv *tftp_do_open(struct device_d *dev,
goto out;
}
- priv->tftp_con = net_udp_new(tpriv->server, TFTP_PORT, tftp_handler,
- priv);
- if (IS_ERR(priv->tftp_con)) {
- ret = PTR_ERR(priv->tftp_con);
- goto out1;
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ priv->tftp_con = net_udp_new(tpriv->server, TFTP_PORT, tftp_handler,
+ priv);
+ if (IS_ERR(priv->tftp_con)) {
+ ret = PTR_ERR(priv->tftp_con);
+ goto out1;
+ }
+
+ ret = tftp_send(priv);
+ if (ret)
+ goto out2;
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ priv->sock = tftp_socket_open(0);
+ if (!priv->sock) {
+ ret = -1;
+ goto out1;
+ }
+
+ priv->sock->priv = priv;
+
+ /* FIXME: add free */
+ priv->pkt = xzalloc(2048);
+ priv->remote_address = tpriv->pserver;
+ priv->remote_port = short_be(TFTP_PORT);
+
+ /* FIXME: convert PICOTCP error code to barebox error code */
+ ret = tftp_send(priv);
+ if (ret == -1)
+ goto out2;
+
+ poller_call();
}
- ret = tftp_send(priv);
- if (ret)
- goto out2;
-
tftp_timer_reset(priv);
while (priv->state != STATE_RDATA &&
priv->state != STATE_DONE &&
@@ -457,7 +581,11 @@ static struct file_priv *tftp_do_open(struct device_d *dev,
return priv;
out2:
- net_unregister(priv->tftp_con);
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ net_unregister(priv->tftp_con);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pico_socket_close(priv->sock);
+ }
out1:
kfifo_free(priv->fifo);
out:
@@ -503,14 +631,32 @@ static int tftp_do_close(struct file_priv *priv)
}
if (!priv->push && priv->state != STATE_DONE) {
- uint16_t *pkt = net_udp_get_payload(priv->tftp_con);
+ uint16_t *pkt;
+
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ pkt = net_udp_get_payload(priv->tftp_con);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pkt = (uint16_t *)priv->pkt;
+ }
+
*pkt++ = htons(TFTP_ERROR);
*pkt++ = 0;
*pkt++ = 0;
- net_udp_send(priv->tftp_con, 6);
+
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ net_udp_send(priv->tftp_con, 6);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pico_socket_sendto(priv->sock, priv->pkt, 6,
+ &priv->remote_address, priv->remote_port);
+ }
+ }
+
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ net_unregister(priv->tftp_con);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ pico_socket_close(priv->sock);
}
- net_unregister(priv->tftp_con);
kfifo_free(priv->fifo);
free(priv->buf);
free(priv);
@@ -630,7 +776,12 @@ static int tftp_probe(struct device_d *dev)
dev->priv = priv;
- priv->server = resolv(fsdev->backingstore);
+ if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+ priv->server = resolv(fsdev->backingstore);
+ } else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+ /* FIXME: check corectness */
+ priv->pserver.ip4.addr = resolv(fsdev->backingstore);
+ }
return 0;
}
--
2.1.4
More information about the barebox
mailing list