diff --git a/net/devif/Make.defs b/net/devif/Make.defs index c95b585d65..fa2d67a1a9 100644 --- a/net/devif/Make.defs +++ b/net/devif/Make.defs @@ -48,6 +48,7 @@ ifeq ($(CONFIG_MM_IOB),y) NET_CSRCS += devif_poll.c NET_CSRCS += devif_iobsend.c + NET_CSRCS += devif_filesend.c endif diff --git a/net/devif/devif.h b/net/devif/devif.h index ea38a7823f..7878c65c4b 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -480,6 +480,27 @@ void devif_iob_send(FAR struct net_driver_s *dev, FAR struct iob_s *buf, unsigned int target_offset); #endif +/**************************************************************************** + * Name: devif_file_send + * + * Description: + * Called from socket logic in response to a xmit or poll request from the + * the network interface driver. + * + * This is identical to calling devif_file_send() except that the data is + * in a available file handle. + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +#ifdef CONFIG_MM_IOB +int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file, + unsigned int len, unsigned int offset, + unsigned int target_offset); +#endif + /**************************************************************************** * Name: devif_out * diff --git a/net/devif/devif_filesend.c b/net/devif/devif_filesend.c new file mode 100644 index 0000000000..5fa2e124f2 --- /dev/null +++ b/net/devif/devif_filesend.c @@ -0,0 +1,160 @@ +/**************************************************************************** + * net/devif/devif_filesend.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_MM_IOB + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devif_file_send + * + * Description: + * Called from socket logic in response to a xmit or poll request from the + * the network interface driver. + * + * This is identical to calling devif_file_send() except that the data is + * in a available file handle. + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file, + unsigned int len, unsigned int offset, + unsigned int target_offset) +{ + FAR struct iob_s *iob; + unsigned int copyin; + unsigned int remain; + int ret; + + if (dev == NULL) + { + ret = -ENODEV; + goto errout; + } + + if (len == 0) + { + ret = -EINVAL; + goto errout; + } + +#ifndef CONFIG_NET_IPFRAG + if (len > NETDEV_PKTSIZE(dev) - NET_LL_HDRLEN(dev) - target_offset) + { + ret = -EMSGSIZE; + goto errout; + } +#endif + + /* Append the send buffer after device buffer */ + + if (len > iob_navail(false) * CONFIG_IOB_BUFSIZE || + netdev_iob_prepare(dev, false, 0) != OK) + { + ret = -ENOMEM; + goto errout; + } + + iob_update_pktlen(dev->d_iob, target_offset); + + ret = file_seek(file, offset, SEEK_SET); + if (ret < 0) + { + goto errout; + } + + iob = dev->d_iob; + remain = len; + + while (remain > 0) + { + if (iob->io_len + iob->io_offset == CONFIG_IOB_BUFSIZE) + { + if (iob->io_flink == NULL) + { + iob->io_flink = iob_tryalloc(false); + if (iob->io_flink == NULL) + { + ret = -ENOMEM; + goto errout; + } + } + + iob = iob->io_flink; + } + + copyin = CONFIG_IOB_BUFSIZE - + (iob->io_len + iob->io_offset); + if (copyin > remain) + { + copyin = remain; + } + + if (copyin > 0) + { + ret = file_read(file, iob->io_data + + (iob->io_len + iob->io_offset), + copyin); + if (ret < 0) + { + goto errout; + } + + iob->io_len += ret; + remain -= ret; + } + } + + iob_update_pktlen(dev->d_iob, target_offset + len); + + dev->d_sndlen = len; + return len; + +errout: + if (ret < 0) + { + netdev_iob_release(dev); + nerr("ERROR: devif_iob_send error: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_MM_IOB */ diff --git a/net/tcp/tcp_sendfile.c b/net/tcp/tcp_sendfile.c index cce1bebbec..b5a6a67107 100644 --- a/net/tcp/tcp_sendfile.c +++ b/net/tcp/tcp_sendfile.c @@ -267,16 +267,9 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev, * happen until the polling cycle completes). */ - ret = file_seek(pstate->snd_file, - pstate->snd_foffset + pstate->snd_acked, SEEK_SET); - if (ret < 0) - { - nerr("ERROR: Failed to lseek: %d\n", ret); - pstate->snd_sent = ret; - goto end_wait; - } - - ret = file_read(pstate->snd_file, dev->d_appdata, sndlen); + ret = devif_file_send(dev, pstate->snd_file, sndlen, + pstate->snd_foffset + pstate->snd_acked, + tcpip_hdrsize(conn)); if (ret < 0) { nerr("ERROR: Failed to read from input file: %d\n", (int)ret); @@ -345,16 +338,9 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev, * happen until the polling cycle completes). */ - ret = file_seek(pstate->snd_file, - pstate->snd_foffset + pstate->snd_sent, SEEK_SET); - if (ret < 0) - { - nerr("ERROR: Failed to lseek: %d\n", ret); - pstate->snd_sent = ret; - goto end_wait; - } - - ret = file_read(pstate->snd_file, dev->d_appdata, sndlen); + ret = devif_file_send(dev, pstate->snd_file, sndlen, + pstate->snd_foffset + pstate->snd_sent, + tcpip_hdrsize(conn)); if (ret < 0) { nerr("ERROR: Failed to read from input file: %d\n", (int)ret);