Compare commits

..

1 Commits

Author SHA1 Message Date
likewise
ccab493c95 Initial import from Adam's 20021017 CVS archive w/ modified license. 2002-10-19 12:59:30 +00:00
479 changed files with 24153 additions and 153243 deletions

10
.gitattributes vendored
View File

@@ -1,10 +0,0 @@
# These files are text and should be normalized
*.txt text
*.c text
*.h text
# For git archive
.gitignore export-ignore
.gitattributes export-ignore
.travis.yml export-ignore
.vscode export-ignore

19
.gitignore vendored
View File

@@ -1,19 +0,0 @@
*.o
*.a
/doc/doxygen/output/html
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler/bin/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler/obj/
/src/apps/snmp/LwipMibCompiler/MibViewer/bin/
/src/apps/snmp/LwipMibCompiler/MibViewer/obj/
/src/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/bin/
/src/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/obj/
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/bin/
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
/src/apps/snmp/LwipMibCompiler/*.suo
/test/fuzz/output
/test/fuzz/lwip_fuzz
/test/fuzz/.depend
/build

4328
CHANGELOG

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
cmake_minimum_required(VERSION 3.7)
project(lwIP)
set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR})
include(src/Filelists.cmake)
# Package generation
set(CPACK_SOURCE_GENERATOR "ZIP")
set(CPACK_SOURCE_PACKAGE_DESCRIPTION_SUMMARY "lwIP lightweight IP stack")
set(CPACK_PACKAGE_VERSION_MAJOR "${LWIP_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${LWIP_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${LWIP_VERSION_REVISION}")
set(CPACK_SOURCE_IGNORE_FILES "/build/;${CPACK_SOURCE_IGNORE_FILES};.git")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "lwip-${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MINOR}.${LWIP_VERSION_REVISION}")
include(CPack)
# Target for package generation
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
add_dependencies(dist lwipdocs)

58
COPYING
View File

@@ -1,33 +1,29 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
Copyright (c) 2001, Swedish Institute of Computer Science.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Institute nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -1,11 +0,0 @@
lwIP is a small independent implementation of the TCP/IP protocol suite targeted at embedded systems.
The focus of the lwIP TCP/IP implementation is to reduce resource usage while still having a full scale TCP. This makes lwIP suitable for use in embedded systems with tens of kilobytes of free RAM and room for around 40 kilobytes of code ROM.
Main features include:
- Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE, 6LowPAN (via IEEE 802.15.4, BLE or ZEP; since v2.1.0)
- DHCP client, stateless DHCPv6 (since v2.1.0), DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3 (since v2.1.0), private MIB support & MIB compiler)
- APIs: specialized APIs for enhanced performance & zero copy, optional Berkeley-alike socket API
- Extended features: IP forwarding over multiple network interfaces
- Extended TCP features: congestion control, RTT estimation and fast recovery/fast retransmit, sending SACKs (since v2.1.0), "altcp": nearly transparent TLS for any tcp pcb (since v2.1.0)
- Addon applications: HTTP server (HTTPS via altcp), HTTP(S) client (since v2.1.0), SNTP client, SMTP client (SMTPS via altcp), ping, NetBIOS nameserver, mDNS responder, MQTT client (TLS support since v2.1.0), TFTP server, iPerf2 counterpart

6
FILES
View File

@@ -1,5 +1,5 @@
src/ - The source code for the lwIP TCP/IP stack.
doc/ - The documentation for lwIP.
test/ - Some code to test whether the sources do what they should.
See also the FILES file in each subdirectory.
proj/ - Makefiles and code for compiling lwIP.
See also the FILES file in each subdirectory.

106
README
View File

@@ -1,106 +0,0 @@
INTRODUCTION
lwIP is a small independent implementation of the TCP/IP protocol suite.
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
while still having a full scale TCP. This making lwIP suitable for use
in embedded systems with tens of kilobytes of free RAM and room for
around 40 kilobytes of code ROM.
lwIP was originally developed by Adam Dunkels at the Computer and Networks
Architectures (CNA) lab at the Swedish Institute of Computer Science (SICS)
and is now developed and maintained by a worldwide network of developers.
FEATURES
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
multiple network interfaces
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
* IGMP (Internet Group Management Protocol) for multicast traffic management
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
RFC 2710. No support for MLDv2
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
(Address autoconfiguration)
* DHCP, AutoIP/APIPA (Zeroconf) and (stateless) DHCPv6
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
fast recovery/fast retransmit and sending SACKs
* raw/native API for enhanced performance
* Optional Berkeley-like socket API
* TLS: optional layered TCP ("altcp") for nearly transparent TLS for any
TCP-based protocol (ported to mbedTLS) (see changelog for more info)
* PPPoS and PPPoE (Point-to-point protocol over Serial/Ethernet)
* DNS (Domain name resolver incl. mDNS)
* 6LoWPAN (via IEEE 802.15.4, BLE or ZEP)
APPLICATIONS
* HTTP server with SSI and CGI (HTTPS via altcp)
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol), v3 via altcp
* SNTP (Simple network time protocol)
* NetBIOS name service responder
* MDNS (Multicast DNS) responder
* iPerf server implementation
* MQTT client (TLS support via altcp)
LICENSE
lwIP is freely available under a BSD license.
DEVELOPMENT
lwIP has grown into an excellent TCP/IP stack for embedded devices,
and developers using the stack often submit bug fixes, improvements,
and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. Everyone can
help improve lwIP by use of Savannah's interface, Git and the
mailing list. A core team of developers will commit changes to the
Git source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
contributions (such as platform ports) are in the 'contrib' Git module.
See doc/savannah.txt for details on Git server access for users and
developers.
The current Git trees are web-browsable:
http://git.savannah.gnu.org/cgit/lwip.git
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/
Continuous integration builds (GCC, clang):
https://travis-ci.org/yarrick/lwip-merged
DOCUMENTATION
Self documentation of the source code is regularly extracted from the current
Git sources and is available from this web page:
http://www.nongnu.org/lwip/
There is now a constantly growing wiki about lwIP at
http://lwip.wikia.com/wiki/LwIP_Wiki
Also, there are mailing lists you can subscribe at
http://savannah.nongnu.org/mail/?group=lwip
plus searchable archives:
http://lists.nongnu.org/archive/html/lwip-users/
http://lists.nongnu.org/archive/html/lwip-devel/
lwIP was originally written by Adam Dunkels:
http://dunkels.com/adam/
Reading Adam's papers, the files in docs/, browsing the source code
documentation and browsing the mailing list archives is a good way to
become familiar with the design of lwIP.
Adam Dunkels <adam@sics.se>
Leon Woestenberg <leon.woestenberg@gmx.net>

278
UPGRADING
View File

@@ -1,278 +0,0 @@
This file lists major changes between release versions that require
ports or applications to be changed. Use it to update a port or an
application written for an older version of lwIP to correctly work
with newer versions.
(git master)
* [Enter new changes just after this line - do not remove this line]
(2.1.0)
++ Application changes:
* Use the new altcp API for seamless TLS integration into existing TCP applications (see changelog)
* TCP only kills existing connections with a LOWER priority than the one currently being opened.
Previous implementations also kill existing connections of the SAME priority.
* ip4_route_src: parameter order is reversed: ip4_route_src(dest, src) -> ip4_route_src(src, dest)
to make parameter order consistent with other ip*_route*() functions.
Same also applies to LWIP_HOOK_IP4_ROUTE_SRC() parameter order.
* pbuf API: pbuf->type (an u8_t holding the enum 'pbuf_type') has changed to only hold a
description of the pbuf (e.g. data following pbuf struct, data volatile, allocation
source heap/pool/etc.). As a consequence, applications can't test pbuf->type any more.
Use pbuf_match_type(pbuf, type) instead.
* socket API: according to the standard, SO_ERROR now only returns asynchronous errors.
All other/normal/synchronous errors are (and always were) available via 'errno'.
LWIP_SOCKET_SET_ERRNO has been removed - 'errno' is always set - and required!
* httpd LWIP_HTTPD_CGI_SSI: httpd_cgi_handler() has an additional parameter "struct fs_file *"
++ Port changes:
* tcpip_trycallback() was renamed to tcpip_callbackmsg_trycallback() to avoid confusion
with tcpip_try_callback()
* compatibility headers: moved from 'src/include/posix' to 'src/include/compat/posix',
'src/include/compat/stdc' etc.
* The IPv6 implementation now supports address scopes. (See LWIP_IPV6_SCOPES documentation
and ip6_zone.h for more documentation)
* LWIP_HOOK_DHCP_APPEND_OPTIONS() has changed, see description in opt.h (options_out_len is not
available in struct dhcp any more)
* Added debug helper asserts to ensure threading/locking requirements are met (define
LWIP_MARK_TCPIP_THREAD() and LWIP_ASSERT_CORE_LOCKED()).
* Added sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
These can be used to post preallocated messages from an ISR to the tcpip thread
(e.g. when using FreeRTOS)
(2.0.2)
++ Application changes:
* slipif: The way to pass serial port number has changed. netif->num is not
supported any more, netif->state is interpreted as an u8_t port number now
(it's not a POINTER to an u8_t any more!)
(2.0.1)
++ Application changes:
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
ip_current_netif() to the desired netif for every packet.
See bug #49662 for an explanation.
(2.0.0)
++ Application changes:
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
has to be set "up" before starting the DHCP client
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
* Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
supports SNMPv2c (experimental v3 support)
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
+++ Raw API:
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
+++ Socket API:
* Added an implementation for posix sendmsg()
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
++ Port changes
+++ new files:
* MANY new and moved files!
* Added src/Filelists.mk for use in Makefile projects
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
to let abc.h only contain the actual application programmer's API
+++ sys layer:
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
open to priority inversion, so this is not recommended any more)
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
instead of using one per netconn (these semaphores are used even with core locking
enabled as some longer lasting functions like big writes still need to delay)
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
in def.h (to be overridden in cc.h) instead of config
options for netbiosns, httpd, dns, etc. ...
* New abstraction for hton* and ntoh* functions in def.h.
To override them, use the following in cc.h:
#define lwip_htons(x) <your_htons>
#define lwip_htonl(x) <your_htonl>
+++ new options:
* TODO
+++ new pools:
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
that share memp.c code but do not have to be made global via lwippools.h
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
is now available
* Signature of LWIP_HOOK_VLAN_SET macro was changed
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
or to move buffers to dedicated memory using compiler attributes
* Standard C headers are used to define sized types and printf formatters
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
does not support these)
++ Major bugfixes/improvements
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Major rewrite of PPP (incl. keep-up with apache pppd)
see doc/ppp.txt for an upgrading how-to
* Major rewrite of SNMP (incl. MIB parser)
* Fixed timing issues that might have lead to losing a DHCP lease
* Made rx processing path more robust against crafted errors
* TCP window scaling support
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
* made DNS client more robust
* support PBUF_REF for RX packets
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
* Moved and reordered stats (mainly memp/mib2)
(1.4.0)
++ Application changes:
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
compatibility to old applications, but will be removed in the future).
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
+++ Raw API:
* Changed the semantics of tcp_close() (since it was rather a
shutdown before): Now the application does *NOT* get any calls to the recv
callback (aside from NULL/closed) after calling tcp_close()
* When calling tcp_abort() from a raw API TCP callback function,
make sure you return ERR_ABRT to prevent accessing unallocated memory.
(ERR_ABRT now means the applicaiton has called tcp_abort!)
+++ Netconn API:
* Changed netconn_receive() and netconn_accept() to return
err_t, not a pointer to new data/netconn.
+++ Socket API:
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
* Added a minimal version of posix fctl() to have a
standardised way to set O_NONBLOCK for nonblocking sockets.
+++ all APIs:
* correctly implemented SO(F)_REUSEADDR
++ Port changes
+++ new files:
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
the actual application programmer's API
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
still want to use your own timer implementation for NO_SYS==0 (as before).
+++ sys layer:
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
sys_sem_t;
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
binary semaphores instead of mutexes - as before)
+++ new options:
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
prevent creating many small pbufs when calling tcp_write with many small
blocks of data. Instead, pbufs are allocated larger than needed and the
space is used for later calls to tcp_write.
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
in tcp_write/udp_send.
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
(necessary for pure PPPoE)
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
be used to place these pools into user-defined memory by using external
declaration.
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
+++ new pools:
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
so MEMP_NUM_NETDB has to be set accordingly.
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
to be set accordingly.
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
has to be set accordingly
* Integrated loopif into netif.c - loopif does not have to be created by the
port any more, just define LWIP_HAVE_LOOPIF to 1.
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
in cc.h, e.g. used by igmp)
* Added printf-formatter X8_F to printf u8_t as hex
* The heap now may be moved to user-defined memory by defining
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
with user-allocated structs instead of calling mem_malloc
* Added const char* name to mem- and memp-stats for easier debugging.
* Calculate the TCP/UDP checksum while copying to only fetch data once:
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
more than one pcb.
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
off any more, if this is set to 0, only one packet (the most recent one) is
queued (like demanded by RFC 1122).
++ Major bugfixes/improvements
* Implemented tcp_shutdown() to only shut down one end of a connection
* Implemented shutdown() at socket- and netconn-level
* Added errorset support to select() + improved select speed overhead
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
* Use macros defined in ip_addr.h to work with IP addresses
* Implemented many nonblocking socket/netconn functions
* Fixed ARP input processing: only add a new entry if a request was directed as us
* mem_realloc() to mem_trim() to prevent confusion with realloc()
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
existing connections when assigning a routable address)
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
* Added support for static ARP table entries
(STABLE-1.3.2)
* initial version of this file

View File

@@ -1,9 +0,0 @@
doxygen/ - Configuration files and scripts to create the lwIP doxygen source
documentation (found at http://www.nongnu.org/lwip/)
savannah.txt - How to obtain the current development source code.
contrib.txt - How to contribute to lwIP as a developer.
rawapi.txt - The documentation for the core API of lwIP.
Also provides an overview about the other APIs and multithreading.
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
ppp.txt - Documentation of the PPP interface for lwIP.

View File

@@ -1,122 +0,0 @@
void
eth_mac_irq()
{
/* Service MAC IRQ here */
/* Allocate pbuf from pool (avoid using heap in interrupts) */
struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL);
if(p != NULL) {
/* Copy ethernet frame into pbuf */
pbuf_take(p, eth_data, eth_data_count);
/* Put in a queue which is processed in main loop */
if(!queue_try_put(&queue, p)) {
/* queue is full -> packet loss */
pbuf_free(p);
}
}
}
static err_t
netif_output(struct netif *netif, struct pbuf *p)
{
LINK_STATS_INC(link.xmit);
/* Update SNMP stats (only if you use SNMP) */
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
int unicast = ((p->payload[0] & 0x01) == 0);
if (unicast) {
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
} else {
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
}
lock_interrupts();
pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0);
/* Start MAC transmit here */
unlock_interrupts();
return ERR_OK;
}
static void
netif_status_callback(struct netif *netif)
{
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
}
static err_t
netif_init(struct netif *netif)
{
netif->linkoutput = netif_output;
netif->output = etharp_output;
netif->output_ip6 = ethip6_output;
netif->mtu = ETHERNET_MTU;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
SMEMCPY(netif->hwaddr, your_mac_address_goes_here, ETH_HWADDR_LEN);
netif->hwaddr_len = ETH_HWADDR_LEN;
return ERR_OK;
}
void
main(void)
{
struct netif netif;
lwip_init();
netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input);
netif.name[0] = 'e';
netif.name[1] = '0';
netif_create_ip6_linklocal_address(&netif, 1);
netif.ip6_autoconfig_enabled = 1;
netif_set_status_callback(&netif, netif_status_callback);
netif_set_default(&netif);
netif_set_up(&netif);
/* Start DHCP and HTTPD */
dhcp_start(&netif );
httpd_init();
while(1) {
/* Check link state, e.g. via MDIO communication with PHY */
if(link_state_changed()) {
if(link_is_up()) {
netif_set_link_up(&netif);
} else {
netif_set_link_down(&netif);
}
}
/* Check for received frames, feed them to lwIP */
lock_interrupts();
struct pbuf* p = queue_try_get(&queue);
unlock_interrupts();
if(p != NULL) {
LINK_STATS_INC(link.recv);
/* Update SNMP stats (only if you use SNMP) */
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
int unicast = ((p->payload[0] & 0x01) == 0);
if (unicast) {
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
} else {
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
}
if(netif.input(p, &netif) != ERR_OK) {
pbuf_free(p);
}
}
/* Cyclic lwIP timers check */
sys_check_timeouts();
/* your application goes here */
}
}

View File

@@ -1,45 +0,0 @@
typedef struct my_custom_pbuf
{
struct pbuf_custom p;
void* dma_descriptor;
} my_custom_pbuf_t;
LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool");
void my_pbuf_free_custom(void* p)
{
SYS_ARCH_DECL_PROTECT(old_level);
my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p;
// invalidate data cache here - lwIP and/or application may have written into buffer!
// (invalidate is faster than flushing, and noone needs the correct data in the buffer)
invalidate_cpu_cache(p->payload, p->tot_len);
SYS_ARCH_PROTECT(old_level);
free_rx_dma_descriptor(my_pbuf->dma_descriptor);
LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf);
SYS_ARCH_UNPROTECT(old_level);
}
void eth_rx_irq()
{
dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet();
my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL);
my_pbuf->p.custom_free_function = my_pbuf_free_custom;
my_pbuf->dma_descriptor = dma_desc;
invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length);
struct pbuf* p = pbuf_alloced_custom(PBUF_RAW,
dma_desc->rx_length,
PBUF_REF,
&my_pbuf->p,
dma_desc->rx_data,
dma_desc->max_buffer_size);
if(netif->input(p, netif) != ERR_OK) {
pbuf_free(p);
}
}

View File

@@ -1,58 +0,0 @@
1 Introduction
This document describes some guidelines for people participating
in lwIP development.
2 How to contribute to lwIP
Here is a short list of suggestions to anybody working with lwIP and
trying to contribute bug reports, fixes, enhancements, platform ports etc.
First of all as you may already know lwIP is a volunteer project so feedback
to fixes or questions might often come late. Hopefully the bug and patch tracking
features of Savannah help us not lose users' input.
2.1 Source code style:
1. do not use tabs.
2. indentation is two spaces per level (i.e. per tab).
3. end debug messages with a trailing newline (\n).
4. one space between keyword and opening bracket.
5. no space between function and opening bracket.
6. one space and no newline before opening curly braces of a block.
7. closing curly brace on a single line.
8. spaces surrounding assignment and comparisons.
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
10. use current source code style as further reference.
2.2 Source code documentation style:
1. JavaDoc compliant and Doxygen compatible.
2. Function documentation above functions in .c files, not .h files.
(This forces you to synchronize documentation and implementation.)
3. Use current documentation style as further reference.
2.3 Bug reports and patches:
1. Make sure you are reporting bugs or send patches against the latest
sources. (From the latest release and/or the current Git sources.)
2. If you think you found a bug make sure it's not already filed in the
bugtracker at Savannah.
3. If you have a fix put the patch on Savannah. If it is a patch that affects
both core and arch specific stuff please separate them so that the core can
be applied separately while leaving the other patch 'open'. The preferred way
is to NOT touch archs you can't test and let maintainers take care of them.
This is a good way to see if they are used at all - the same goes for unix
netifs except tapif.
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
or a patch will be enough.
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other
trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you
change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than
if it's not to the point and long :) so the chances for it to be applied are greater.
2.4 Platform porters:
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
you think it could benefit others[1] you might want discuss this on the mailing list. You
can also ask for Git access to submit and maintain your port in the contrib Git module.

View File

@@ -1 +0,0 @@
doxygen lwip.Doxyfile

View File

@@ -1,3 +0,0 @@
#!/bin/sh
doxygen lwip.Doxyfile

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,412 +0,0 @@
/**
* @defgroup lwip lwIP
*
* @defgroup infrastructure Infrastructure
*
* @defgroup api APIs
* lwIP provides three Application Program's Interfaces (APIs) for programs
* to use for communication with the TCP/IP code:
* - low-level "core" / "callback" or @ref callbackstyle_api.
* - higher-level @ref sequential_api.
* - BSD-style @ref socket.
*
* The raw TCP/IP interface allows the application program to integrate
* better with the TCP/IP code. Program execution is event based by
* having callback functions being called from within the TCP/IP
* code. The TCP/IP code and the application program both run in the same
* thread. The sequential API has a much higher overhead and is not very
* well suited for small systems since it forces a multithreaded paradigm
* on the application.
*
* The raw TCP/IP interface is not only faster in terms of code execution
* time but is also less memory intensive. The drawback is that program
* development is somewhat harder and application programs written for
* the raw TCP/IP interface are more difficult to understand. Still, this
* is the preferred way of writing applications that should be small in
* code size and memory usage.
*
* All APIs can be used simultaneously by different application
* programs. In fact, the sequential API is implemented as an application
* program using the raw TCP/IP interface.
*
* Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
* The former is a way of interfacing the lwIP network stack (including
* TCP and UDP), the latter refers to processing raw Ethernet or IP data
* instead of TCP connections or UDP packets.
*
* Raw API applications may never block since all packet processing
* (input and output) as well as timer processing (TCP mainly) is done
* in a single execution context.
*
* @defgroup callbackstyle_api "raw" APIs
* @ingroup api
* Non thread-safe APIs, callback style for maximum performance and minimum
* memory footprint.
* Program execution is driven by callbacks functions, which are then
* invoked by the lwIP core when activity related to that application
* occurs. A particular application may register to be notified via a
* callback function for events such as incoming data available, outgoing
* data sent, error notifications, poll timer expiration, connection
* closed, etc. An application can provide a callback function to perform
* processing for any or all of these events. Each callback is an ordinary
* C function that is called from within the TCP/IP code. Every callback
* function is passed the current TCP or UDP connection state as an
* argument. Also, in order to be able to keep program specific state,
* the callback functions are called with a program specified argument
* that is independent of the TCP/IP state.
* The raw API (sometimes called native API) is an event-driven API designed
* to be used without an operating system that implements zero-copy send and
* receive. This API is also used by the core stack for interaction between
* the various protocols. It is the only API available when running lwIP
* without an operating system.
*
* @defgroup sequential_api Sequential-style APIs
* @ingroup api
* Sequential-style APIs, blocking functions. More overhead, but can be called
* from any thread except TCPIP thread.
* The sequential API provides a way for ordinary, sequential, programs
* to use the lwIP stack. It is quite similar to the BSD socket API. The
* model of execution is based on the blocking open-read-write-close
* paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
* code and the application program must reside in different execution
* contexts (threads).
*
* @defgroup socket Socket API
* @ingroup api
* BSD-style socket API.\n
* Thread-safe, to be called from non-TCPIP threads only.\n
* Can be activated by defining @ref LWIP_SOCKET to 1.\n
* Header is in posix/sys/socket.h\n
* The socket API is a compatibility API for existing applications,
* currently it is built on top of the sequential API. It is meant to
* provide all functions needed to run socket API applications running
* on other platforms (e.g. unix / windows etc.). However, due to limitations
* in the specification of this API, there might be incompatibilities
* that require small modifications of existing programs.
*
* @defgroup netifs NETIFs
*
* @defgroup apps Applications
*/
/**
* @mainpage Overview
* @verbinclude "README"
*/
/**
* @page upgrading Upgrading
* @verbinclude "UPGRADING"
*/
/**
* @page changelog Changelog
*
* 2.1.0
* -----
* * Support TLS via new @ref altcp_api connection API (https, smtps, mqtt over TLS)
* * Switch to cmake as the main build system (Makefile file lists are still
* maintained for now)
* * Improve IPv6 support: support address scopes, support stateless DHCPv6, bugfixes
* * Add debug helper asserts to ensure threading/locking requirements are met
* * Add sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
* (for FreeRTOS, mainly)
* * socket API: support poll(), sendmsg() and recvmsg(); fix problems on close
*
* Detailed Changelog
* ------------------
* @verbinclude "CHANGELOG"
*/
/**
* @page contrib How to contribute to lwIP
* @verbinclude "contrib.txt"
*/
/**
* @page pitfalls Common pitfalls
*
* Multiple Execution Contexts in lwIP code
* ========================================
*
* The most common source of lwIP problems is to have multiple execution contexts
* inside the lwIP code.
*
* lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
* running on target system) or @ref lwip_os (there is an OS running
* on the target system).
*
* See also: @ref multithreading (especially the part about @ref LWIP_ASSERT_CORE_LOCKED()!)
*
* Mainloop Mode
* -------------
* In mainloop mode, only @ref callbackstyle_api can be used.
* The user has two possibilities to ensure there is only one
* exection context at a time in lwIP:
*
* 1) Deliver RX ethernet packets directly in interrupt context to lwIP
* by calling netif->input directly in interrupt. This implies all lwIP
* callback functions are called in IRQ context, which may cause further
* problems in application code: IRQ is blocked for a long time, multiple
* execution contexts in application code etc. When the application wants
* to call lwIP, it only needs to disable interrupts during the call.
* If timers are involved, even more locking code is needed to lock out
* timer IRQ and ethernet IRQ from each other, assuming these may be nested.
*
* 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
* lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
* has to put received telegrams into a queue which is polled in the
* mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
*
* OS Mode
* -------
* In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
* @ref sequential_api are designed to be called from threads other than
* the TCPIP thread, so there is nothing to consider here.
* But @ref callbackstyle_api functions must _ONLY_ be called from
* TCPIP thread. It is a common error to call these from other threads
* or from IRQ contexts. Ethernet RX needs to deliver incoming packets
* in the correct way by sending a message to TCPIP thread, this is
* implemented in tcpip_input().
* Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
*
* 1) tcpip_callback() can be used get called back from TCPIP thread,
* it is safe to call any @ref callbackstyle_api from there.
*
* 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
* functions can be called when lwIP core lock is aquired, see
* @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
* These macros cannot be used in an interrupt context!
* Note the OS must correctly handle priority inversion for this.
*
* Cache / DMA issues
* ==================
*
* DMA-capable ethernet hardware and zero-copy RX
* ----------------------------------------------
*
* lwIP changes the content of RECEIVED pbufs in the TCP code path.
* This implies one or more cacheline(s) of the RX pbuf become dirty
* and need to be flushed before the memory is handed over to the
* DMA ethernet hardware for the next telegram to be received.
* See http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html
* for a more detailed explanation.
* Also keep in mind the user application may also write into pbufs,
* so it is generally a bug not to flush the data cache before handing
* a buffer to DMA hardware.
*
* DMA-capable ethernet hardware and cacheline alignment
* -----------------------------------------------------
* Nice description about DMA capable hardware and buffer handling:
* http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/
* Read especially sections "Cache coherency" and "Buffer alignment".
*/
/**
* @page mem_err Debugging memory pool sizes
* If you have issues with lwIP and you are using memory pools, check that your pools
* are correctly sized.\n
* To debug pool sizes, \#define LWIP_STATS and MEMP_STATS to 1. Check the global variable
* lwip_stats.memp[] using a debugger. If the "err" member of a pool is > 0, the pool
* may be too small for your application and you need to increase its size.
*/
/**
* @page bugs Reporting bugs
* Please report bugs in the lwIP bug tracker at savannah.\n
* BEFORE submitting, please check if the bug has already been reported!\n
* https://savannah.nongnu.org/bugs/?group=lwip
*/
/**
* @page zerocopyrx Zero-copy RX
* The following code is an example for zero-copy RX ethernet driver:
* @include ZeroCopyRx.c
*/
/**
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
* @ingroup lwip
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
* context and put them into a queue which is processed from mainloop.\n
* Call sys_check_timeouts() periodically in the mainloop.\n
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
* @ref compiler_abstraction.\n
* You can only use @ref callbackstyle_api in this mode.\n
* Sample code:\n
* @include NO_SYS_SampleCode.c
*/
/**
* @defgroup lwip_os OS mode (TCPIP thread)
* @ingroup lwip
* Use this mode if you run an OS on your system. It is recommended to
* use an RTOS that correctly handles priority inversion and
* to use @ref LWIP_TCPIP_CORE_LOCKING.\n
* Porting: implement all functions in @ref sys_layer.\n
* You can use @ref callbackstyle_api together with @ref tcpip_callback,
* and all @ref sequential_api.
*/
/**
* @page sys_init System initalization
A truly complete and generic sequence for initializing the lwIP stack
cannot be given because it depends on additional initializations for
your runtime environment (e.g. timers).
We can give you some idea on how to proceed when using the raw API.
We assume a configuration using a single Ethernet netif and the
UDP and TCP transport layers, IPv4 and the DHCP client.
Call these functions in the order of appearance:
- lwip_init(): Initialize the lwIP stack and all of its subsystems.
- netif_add(struct netif *netif, ...):
Adds your network interface to the netif_list. Allocate a struct
netif and pass a pointer to this structure as the first argument.
Give pointers to cleared ip_addr structures when using DHCP,
or fill them with sane numbers otherwise. The state pointer may be NULL.
The init function pointer must point to a initialization function for
your Ethernet netif interface. The following code illustrates its use.
@code{.c}
err_t netif_if_init(struct netif *netif)
{
u8_t i;
for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
netif->hwaddr[i] = some_eth_addr[i];
}
init_my_eth_device();
return ERR_OK;
}
@endcode
For Ethernet drivers, the input function pointer must point to the lwIP
function ethernet_input() declared in "netif/etharp.h". Other drivers
must use ip_input() declared in "lwip/ip.h".
- netif_set_default(struct netif *netif)
Registers the default network interface.
- netif_set_link_up(struct netif *netif)
This is the hardware link state; e.g. whether cable is plugged for wired
Ethernet interface. This function must be called even if you don't know
the current state. Having link up and link down events is optional but
DHCP and IPv6 discover benefit well from those events.
- netif_set_up(struct netif *netif)
This is the administrative (= software) state of the netif, when the
netif is fully configured this function must be called.
- dhcp_start(struct netif *netif)
Creates a new DHCP client for this interface on the first call.
You can peek in the netif->dhcp struct for the actual DHCP status.
- sys_check_timeouts()
When the system is running, you have to periodically call
sys_check_timeouts() which will handle all timers for all protocols in
the stack; add this to your main loop or equivalent.
*/
/**
* @page multithreading Multithreading
* lwIP started targeting single-threaded environments. When adding multi-
* threading support, instead of making the core thread-safe, another
* approach was chosen: there is one main thread running the lwIP core
* (also known as the "tcpip_thread"). When running in a multithreaded
* environment, raw API functions MUST only be called from the core thread
* since raw API functions are not protected from concurrent access (aside
* from pbuf- and memory management functions). Application threads using
* the sequential- or socket API communicate with this main thread through
* message passing.
*
* As such, the list of functions that may be called from
* other threads or an ISR is very limited! Only functions
* from these API header files are thread-safe:
* - api.h
* - netbuf.h
* - netdb.h
* - netifapi.h
* - pppapi.h
* - sockets.h
* - sys.h
*
* Additionaly, memory (de-)allocation functions may be
* called from multiple threads (not ISR!) with NO_SYS=0
* since they are protected by @ref SYS_LIGHTWEIGHT_PROT and/or
* semaphores.
*
* Netconn or Socket API functions are thread safe against the
* core thread but they are not reentrant at the control block
* granularity level. That is, a UDP or TCP control block must
* not be shared among multiple threads without proper locking.
*
* If @ref SYS_LIGHTWEIGHT_PROT is set to 1 and
* @ref LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
* pbuf_free() may also be called from another thread or
* an ISR (since only then, mem_free - for PBUF_RAM - may
* be called from an ISR: otherwise, the HEAP is only
* protected by semaphores).
*
* How to get threading done right
* -------------------------------
*
* It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED()
* macro in an application that uses multithreading. lwIP code has
* several places where a check for a correct thread context is
* implemented which greatly helps the user to get threading done right.
* See the example sys_arch.c files in unix and Win32 port
* in the contrib repository.
*
* In short: Copy the functions sys_mark_tcpip_thread() and
* sys_check_core_locking() to your port and modify them to work with your OS.
* Then let @ref LWIP_ASSERT_CORE_LOCKED() and @ref LWIP_MARK_TCPIP_THREAD()
* point to these functions.
*
* If you use @ref LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt
* the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core().
* Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point
* to these functions.
*/
/**
* @page optimization Optimization hints
The first thing you want to optimize is the lwip_standard_checksum()
routine from src/core/inet.c. You can override this standard
function with the \#define LWIP_CHKSUM your_checksum_routine().
There are C examples given in inet.c or you might want to
craft an assembly function for this. RFC1071 is a good
introduction to this subject.
Other significant improvements can be made by supplying
assembly or inline replacements for htons() and htonl()
if you're using a little-endian architecture.
\#define lwip_htons(x) your_htons()
\#define lwip_htonl(x) your_htonl()
If you \#define them to htons() and htonl(), you should
\#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
defining htonx / ntohx compatibility macros.
Check your network interface driver if it reads at
a higher speed than the maximum wire-speed. If the
hardware isn't serviced frequently and fast enough
buffer overflows are likely to occur.
E.g. when using the cs8900 driver, call cs8900if_service(ethif)
as frequently as possible. When using an RTOS let the cs8900 interrupt
wake a high priority task that services your driver using a binary
semaphore or event flag. Some drivers might allow additional tuning
to match your application and network.
For a production release it is recommended to set LWIP_STATS to 0.
Note that speed performance isn't influenced much by simply setting
high values to the memory options.
*/

View File

@@ -1,10 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Redirection</title>
<meta http-equiv="refresh" content="0; url=html/index.html" />
</head>
<body>
<a href="html/index.html">index.html</a>
</body>
</html>

View File

@@ -1,112 +0,0 @@
Multicast DNS for lwIP
Author: Erik Ekman
Note! The MDNS responder does not have all features required by the standards.
See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal
cases - but watch out if many devices on the same network try to use the same
host/service instance names.
How to enable:
==============
MDNS support does not depend on DNS.
MDNS supports using IPv4 only, v6 only, or v4+v6.
To enable MDNS responder, set
LWIP_MDNS_RESPONDER = 1
in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build.
The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
default is 1.
Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB.
Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif).
MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
generated.
The MDNS code puts its structs on the stack where suitable to reduce dynamic
memory allocation. It may use up to 1kB of stack.
MDNS (like other apps) needs a strncasecmp() implementation. If you have one, define
'lwip_strnicmp' to it. Otherwise the code will provide an implementation
for you.
How to use:
===========
Call mdns_resp_init() during system initialization.
This opens UDP sockets on port 5353 for IPv4 and IPv6.
To start responding on a netif, run
mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
The hostname will be copied. If this returns successfully, the netif will join
the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
to port 5353 will be handled:
- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
returns <hostname>.local
Answers will use the supplied TTL (in seconds)
MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
since the default case-insensitive comparison assumes this.
Call mdns_resp_announce() every time the IP address on the netif has changed.
Call mdns_resp_restart() every time the network interface comes up after being
down, for example cable connected after being disconnected, administrative
interface comes up after being down, or the device wakes up from sleep.
To stop responding on a netif, run
mdns_resp_remove_netif(struct netif *netif)
Adding services:
================
The netif first needs to be registered. Then run
mdns_resp_add_service(struct netif *netif, char *name, char *service,
u16_t proto, u16_t port, u32_t dns_ttl,
service_get_txt_fn_t txt_fn, void *txt_userdata);
The name and service pointers will be copied. Name refers to the name of the
service instance, and service is the type of service, like _http
proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
If this call returns successfully, the following queries will be answered:
- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
- <name>.<service>.<proto>.local type SRV returns hostname and port of service
- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
with the supplied userdata. The callback adds strings to the reply by calling
mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
int txt_len). Example callback method:
static void srv_txt(struct mdns_service *service, void *txt_userdata)
{
res = mdns_resp_add_service_txtitem(service, "path=/", 6);
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
}
Since a hostname struct is used for TXT storage each single item can be max
63 bytes long, and the total max length (including length bytes for each
item) is 255 bytes.
If your device runs a webserver on port 80, an example call might be:
mdns_resp_add_service(netif, "myweb", "_http"
DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
which will publish myweb._http._tcp.local for any hosts looking for web servers,
and point them to <hostname>.local:80
Relevant information will be sent as additional records to reduce number of
requests required from a client.
To remove a service from a netif, run
mdns_resp_del_service(struct netif *netif, s8_t slot)

View File

@@ -1,162 +0,0 @@
MQTT client for lwIP
Author: Erik Andersson
Details of the MQTT protocol can be found at:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
-----------------------------------------------------------------
1. Initial steps, reserve memory and make connection to server:
1.1: Provide storage
Static allocation:
mqtt_client_t static_client;
example_do_connect(&static_client);
Dynamic allocation:
mqtt_client_t *client = mqtt_client_new();
if(client != NULL) {
example_do_connect(&client);
}
1.2: Establish Connection with server
void example_do_connect(mqtt_client_t *client)
{
struct mqtt_connect_client_info_t ci;
err_t err;
/* Setup an empty client info structure */
memset(&ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "lwip_test";
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
/* For now just print the result code if something goes wrong */
if(err != ERR_OK) {
printf("mqtt_connect return %d\n", err);
}
}
Connection to server can also be probed by calling mqtt_client_is_connected(client)
-----------------------------------------------------------------
2. Implementing the connection status callback
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
{
err_t err;
if(status == MQTT_CONNECT_ACCEPTED) {
printf("mqtt_connection_cb: Successfully connected\n");
/* Setup callback for incoming publish requests */
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
if(err != ERR_OK) {
printf("mqtt_subscribe return: %d\n", err);
}
} else {
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
/* Its more nice to be connected, so try to reconnect */
example_do_connect(client);
}
}
static void mqtt_sub_request_cb(void *arg, err_t result)
{
/* Just print the result code here for simplicity,
normal behaviour would be to take some action if subscribe fails like
notifying user, retry subscribe or disconnect from server */
printf("Subscribe result: %d\n", result);
}
-----------------------------------------------------------------
3. Implementing callbacks for incoming publish and data
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
Example here uses a global variable, better would be to use a member in arg
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
the topic string and use it in mqtt_incoming_data_cb
*/
static int inpub_id;
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
{
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
/* Decode topic string into a user defined reference */
if(strcmp(topic, "print_payload") == 0) {
inpub_id = 0;
} else if(topic[0] == 'A') {
/* All topics starting with 'A' might be handled at the same way */
inpub_id = 1;
} else {
/* For all other topics */
inpub_id = 2;
}
}
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
{
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
if(flags & MQTT_DATA_FLAG_LAST) {
/* Last fragment of payload received (or whole part if payload fits receive buffer
See MQTT_VAR_HEADER_BUFFER_LEN) */
/* Call function or do action depending on reference, in this case inpub_id */
if(inpub_id == 0) {
/* Don't trust the publisher, check zero termination */
if(data[len-1] == 0) {
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
}
} else if(inpub_id == 1) {
/* Call an 'A' function... */
} else {
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
}
} else {
/* Handle fragmented payload, store in buffer, write to file or whatever */
}
}
-----------------------------------------------------------------
4. Using outgoing publish
void example_publish(mqtt_client_t *client, void *arg)
{
const char *pub_payload= "PubSubHubLubJub";
err_t err;
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
u8_t retain = 0; /* No don't retain such crappy payload... */
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
if(err != ERR_OK) {
printf("Publish err: %d\n", err);
}
}
/* Called when publish is complete either with sucess or failure */
static void mqtt_pub_request_cb(void *arg, err_t result)
{
if(result != ERR_OK) {
printf("Publish result: %d\n", result);
}
}
-----------------------------------------------------------------
5. Disconnecting
Simply call mqtt_disconnect(client)

View File

@@ -1,529 +0,0 @@
PPP interface for lwIP
Author: Sylvain Rochet
Table of Contents:
1 - Supported PPP protocols and features
2 - Raw API PPP example for all protocols
3 - PPPoS input path (raw API, IRQ safe API, TCPIP API)
4 - Thread safe PPP API (PPPAPI)
5 - Notify phase callback (PPP_NOTIFY_PHASE)
6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
1 Supported PPP protocols and features
======================================
Supported Low level protocols:
* PPP over serial using HDLC-like framing, such as wired dialup modems
or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems
* PPP over Ethernet, such as xDSL modems
* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),
IP tunnel over UDP, such as VPN access
Supported auth protocols:
* PAP, Password Authentication Protocol
* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5
* MSCHAPv1, Microsoft version of CHAP, version 1
* MSCHAPv2, Microsoft version of CHAP, version 2
* EAP, Extensible Authentication Protocol
Supported address protocols:
* IPCP, IP Control Protocol, IPv4 addresses negotiation
* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
Supported encryption protocols:
* MPPE, Microsoft Point-to-Point Encryption
Supported compression or miscellaneous protocols, for serial links only:
* PFC, Protocol Field Compression
* ACFC, Address-and-Control-Field-Compression
* ACCM, Asynchronous-Control-Character-Map
* VJ, Van Jacobson TCP/IP Header Compression
2 Raw API PPP example for all protocols
=======================================
As usual, raw API for lwIP means the lightweight API which *MUST* only be used
for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.
/*
* Globals
* =======
*/
/* The PPP control block */
ppp_pcb *ppp;
/* The PPP IP interface */
struct netif ppp_netif;
/*
* PPP status callback
* ===================
*
* PPP status callback is called on PPP status change (up, down, …) from lwIP
* core thread
*/
/* PPP status callback example */
static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
struct netif *pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch(err_code) {
case PPPERR_NONE: {
#if LWIP_DNS
const ip_addr_t *ns;
#endif /* LWIP_DNS */
printf("status_cb: Connected\n");
#if PPP_IPV4_SUPPORT
printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));
printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
#if LWIP_DNS
ns = dns_getserver(0);
printf(" dns1 = %s\n", ipaddr_ntoa(ns));
ns = dns_getserver(1);
printf(" dns2 = %s\n", ipaddr_ntoa(ns));
#endif /* LWIP_DNS */
#endif /* PPP_IPV4_SUPPORT */
#if PPP_IPV6_SUPPORT
printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif /* PPP_IPV6_SUPPORT */
break;
}
case PPPERR_PARAM: {
printf("status_cb: Invalid parameter\n");
break;
}
case PPPERR_OPEN: {
printf("status_cb: Unable to open PPP session\n");
break;
}
case PPPERR_DEVICE: {
printf("status_cb: Invalid I/O device for PPP\n");
break;
}
case PPPERR_ALLOC: {
printf("status_cb: Unable to allocate resources\n");
break;
}
case PPPERR_USER: {
printf("status_cb: User interrupt\n");
break;
}
case PPPERR_CONNECT: {
printf("status_cb: Connection lost\n");
break;
}
case PPPERR_AUTHFAIL: {
printf("status_cb: Failed authentication challenge\n");
break;
}
case PPPERR_PROTOCOL: {
printf("status_cb: Failed to meet protocol\n");
break;
}
case PPPERR_PEERDEAD: {
printf("status_cb: Connection timeout\n");
break;
}
case PPPERR_IDLETIMEOUT: {
printf("status_cb: Idle Timeout\n");
break;
}
case PPPERR_CONNECTTIME: {
printf("status_cb: Max connect time reached\n");
break;
}
case PPPERR_LOOPBACK: {
printf("status_cb: Loopback detected\n");
break;
}
default: {
printf("status_cb: Unknown error code %d\n", err_code);
break;
}
}
/*
* This should be in the switch case, this is put outside of the switch
* case for example readability.
*/
if (err_code == PPPERR_NONE) {
return;
}
/* ppp_close() was previously called, don't reconnect */
if (err_code == PPPERR_USER) {
/* ppp_free(); -- can be called here */
return;
}
/*
* Try to reconnect in 30 seconds, if you need a modem chatscript you have
* to do a much better signaling here ;-)
*/
ppp_connect(pcb, 30);
/* OR ppp_listen(pcb); */
}
/*
* Creating a new PPPoS session
* ============================
*
* In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.
*/
#include "netif/ppp/pppos.h"
/*
* PPPoS serial output callback
*
* ppp_pcb, PPP control block
* data, buffer to write to serial port
* len, length of the data buffer
* ctx, optional user-provided callback context pointer
*
* Return value: len if write succeed
*/
static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
return uart_write(UART, data, len);
}
/*
* Create a new PPPoS interface
*
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
* output_cb, PPPoS serial output callback
* status_cb, PPP status callback, called on PPP status change (up, down, …)
* ctx_cb, optional user-provided callback context pointer
*/
ppp = pppos_create(&ppp_netif,
output_cb, status_cb, ctx_cb);
/*
* Creating a new PPPoE session
* ============================
*/
#include "netif/ppp/pppoe.h"
/*
* Create a new PPPoE interface
*
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
* ethif, already existing and setup Ethernet interface to use
* service_name, PPPoE service name discriminator (not supported yet)
* concentrator_name, PPPoE concentrator name discriminator (not supported yet)
* status_cb, PPP status callback, called on PPP status change (up, down, …)
* ctx_cb, optional user-provided callback context pointer
*/
ppp = pppoe_create(&ppp_netif,
&ethif,
service_name, concentrator_name,
status_cb, ctx_cb);
/*
* Creating a new PPPoL2TP session
* ===============================
*/
#include "netif/ppp/pppol2tp.h"
/*
* Create a new PPPoL2TP interface
*
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
* netif, optional already existing and setup output netif, necessary if you
* want to set this interface as default route to settle the chicken
* and egg problem with VPN links
* ipaddr, IP to connect to
* port, UDP port to connect to (usually 1701)
* secret, L2TP secret to use
* secret_len, size in bytes of the L2TP secret
* status_cb, PPP status callback, called on PPP status change (up, down, …)
* ctx_cb, optional user-provided callback context pointer
*/
ppp = pppol2tp_create(&ppp_netif,
struct netif *netif, ip_addr_t *ipaddr, u16_t port,
u8_t *secret, u8_t secret_len,
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
/*
* Initiate PPP client connection
* ==============================
*/
/* Set this interface as default route */
ppp_set_default(ppp);
/*
* Basic PPP client configuration. Can only be set if PPP session is in the
* dead state (i.e. disconnected). We don't need to provide thread-safe
* equivalents through PPPAPI because those helpers are only changing
* structure members while session is inactive for lwIP core. Configuration
* only need to be done once.
*/
/* Ask the peer for up to 2 DNS server addresses. */
ppp_set_usepeerdns(ppp, 1);
/* Auth configuration, this is pretty self-explanatory */
ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
/*
* Initiate PPP negotiation, without waiting (holdoff=0), can only be called
* if PPP session is in the dead state (i.e. disconnected).
*/
u16_t holdoff = 0;
ppp_connect(ppp, holdoff);
/*
* Initiate PPP server listener
* ============================
*/
/*
* Basic PPP server configuration. Can only be set if PPP session is in the
* dead state (i.e. disconnected). We don't need to provide thread-safe
* equivalents through PPPAPI because those helpers are only changing
* structure members while session is inactive for lwIP core. Configuration
* only need to be done once.
*/
ip4_addr_t addr;
/* Set our address */
IP4_ADDR(&addr, 192,168,0,1);
ppp_set_ipcp_ouraddr(ppp, &addr);
/* Set peer(his) address */
IP4_ADDR(&addr, 192,168,0,2);
ppp_set_ipcp_hisaddr(ppp, &addr);
/* Set primary DNS server */
IP4_ADDR(&addr, 192,168,10,20);
ppp_set_ipcp_dnsaddr(ppp, 0, &addr);
/* Set secondary DNS server */
IP4_ADDR(&addr, 192,168,10,21);
ppp_set_ipcp_dnsaddr(ppp, 1, &addr);
/* Auth configuration, this is pretty self-explanatory */
ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
/* Require peer to authenticate */
ppp_set_auth_required(ppp, 1);
/*
* Only for PPPoS, the PPP session should be up and waiting for input.
*
* Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.
* The listen call is meant for future support of PPPoE and PPPoL2TP server
* mode, where we will need to negotiate the incoming PPPoE session or L2TP
* session before initiating PPP itself. We need this call because there is
* two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.
*/
ppp_set_silent(pppos, 1);
/*
* Initiate PPP listener (i.e. wait for an incoming connection), can only
* be called if PPP session is in the dead state (i.e. disconnected).
*/
ppp_listen(ppp);
/*
* Closing PPP connection
* ======================
*/
/*
* Initiate the end of the PPP session, without carrier lost signal
* (nocarrier=0), meaning a clean shutdown of PPP protocols.
* You can call this function at anytime.
*/
u8_t nocarrier = 0;
ppp_close(ppp, nocarrier);
/*
* Then you must wait your status_cb() to be called, it may takes from a few
* seconds to several tens of seconds depending on the current PPP state.
*/
/*
* Freeing a PPP connection
* ========================
*/
/*
* Free the PPP control block, can only be called if PPP session is in the
* dead state (i.e. disconnected). You need to call ppp_close() before.
*/
ppp_free(ppp);
3 PPPoS input path (raw API, IRQ safe API, TCPIP API)
=====================================================
Received data on serial port should be sent to lwIP using the pppos_input()
function or the pppos_input_tcpip() function.
If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
is not IRQ safe and then *MUST* only be called inside your main loop.
Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
safe and can be safely called from an interrupt context, using that is going
to reduce your need of buffer if pppos_input() is called byte after byte in
your rx serial interrupt.
if NO_SYS is 0, the thread safe way outside an interrupt context is to use
the pppos_input_tcpip() function to pass input data to the lwIP core thread
using the TCPIP API. This is thread safe in all cases but you should avoid
passing data byte after byte because it uses heavy locking (mailbox) and it
allocates pbuf, better fill them !
if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
from an RX thread, however pppos_input() is not thread safe by itself. You can
do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
really know what you are doing, your move ;-)
/*
* Fonction to call for received data
*
* ppp, PPP control block
* buffer, input buffer
* buffer_len, buffer length in bytes
*/
void pppos_input(ppp, buffer, buffer_len);
or
void pppos_input_tcpip(ppp, buffer, buffer_len);
4 Thread safe PPP API (PPPAPI)
==============================
There is a thread safe API for all corresponding ppp_* functions, you have to
enable LWIP_PPP_API in your lwipopts.h file, then see
include/netif/ppp/pppapi.h, this is actually pretty obvious.
5 Notify phase callback (PPP_NOTIFY_PHASE)
==========================================
Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
you configure a callback that is called on each PPP internal state change.
This is different from the status callback which only warns you about
up(running) and down(dead) events.
Notify phase callback can be used, for example, to set a LED pattern depending
on the current phase of the PPP session. Here is a callback example which
tries to mimic what we usually see on xDSL modems while they are negotiating
the link, which should be self-explanatory:
static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {
switch (phase) {
/* Session is down (either permanently or briefly) */
case PPP_PHASE_DEAD:
led_set(PPP_LED, LED_OFF);
break;
/* We are between two sessions */
case PPP_PHASE_HOLDOFF:
led_set(PPP_LED, LED_SLOW_BLINK);
break;
/* Session just started */
case PPP_PHASE_INITIALIZE:
led_set(PPP_LED, LED_FAST_BLINK);
break;
/* Session is running */
case PPP_PHASE_RUNNING:
led_set(PPP_LED, LED_ON);
break;
default:
break;
}
}
6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
===============================================
PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting
from previous lwIP version is pretty easy:
* Previous PPP API used an integer to identify PPP sessions, we are now
using ppp_pcb* control block, therefore all functions changed from "int ppp"
to "ppp_pcb *ppp"
* struct netif was moved outside the PPP structure, you have to provide a netif
for PPP interface in pppoX_create() functions
* PPP session are not started automatically after you created them anymore,
you have to call ppp_connect(), this way you can configure the session before
starting it.
* Previous PPP API used CamelCase, we are now using snake_case.
* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,
PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed
pppoe_, common functions are now prefixed ppp_.
* New PPPERR_ error codes added, check you have all of them in your status
callback function
* Only the following include files should now be used in user application:
#include "netif/ppp/pppapi.h"
#include "netif/ppp/pppos.h"
#include "netif/ppp/pppoe.h"
#include "netif/ppp/pppol2tp.h"
Functions from ppp.h can be used, but you don't need to include this header
file as it is already included by above header files.
* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
your own serial rx thread
* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
because you might have been fooled by that
* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
the PPPAPI API instead.
* ppp_sighup and ppp_close functions were merged using an optional argument
"nocarrier" on ppp_close.
* DNS servers are now only remotely asked if LWIP_DNS is set and if
ppp_set_usepeerdns() is set to true, they are now automatically registered
using the dns_setserver() function so you don't need to do that in the PPP
callback anymore.
* PPPoS does not use the SIO API anymore, as such it now requires a serial
output callback in place of sio_write
* PPP_MAXIDLEFLAG is now in ms instead of jiffies

289
doc/rawapi.txt Normal file
View File

@@ -0,0 +1,289 @@
Raw TCP/IP interface for lwIP 0.5
Author: Adam Dunkels
$Id: rawapi.txt,v 1.1.1.1 2002/10/19 12:59:32 likewise Exp $
lwIP provides two Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code: the sequential API
(often just called "the API") and the raw TCP/IP interface. This
document is intended as a description of the latter. For lwIP versions
lower than 0.5, this API was not documented.
The sequential API provides a way for ordinary, sequential, programs
to use the lwIP stack. It is quite similar to the BSD socket API. The
model of execution is based on the open-read-write-close
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
code and the application program must reside in different execution
contexts (threads).
The raw TCP/IP interface allows the application program to integrate
better with the TCP/IP code. Program execution is event based by
having callback functions being called from within the TCP/IP
code. The TCP/IP code and the application program both run in the same
thread. The sequential API has a much higher overhead and is not very
well suited for small systems since it forces a multithreaded paradigm
on the application.
The raw TCP/IP interface is not only faster in terms of code execution
time but is also less memory intensive. The drawback is that program
development is somewhat harder and application programs written for
the raw TCP/IP interface are more difficult to understand. Still, this
is the preferred way of writing applications that should be small in
code size and memory usage.
Both APIs can be used simultaneously by different application
programs. In fact, the sequential API is implemented as an application
program using the raw TCP/IP interface.
--- Callbacks
Program execution is driven by callbacks. Each callback is an ordinary
C function that is called from within the TCP/IP code. Every callback
function is passed the current TCP or UDP connection state as an
argument. Also, in order to be able to keep program specific state,
the callback functions are called with a program specified argument
that is independent of the TCP/IP state.
The function for setting the application connection state is:
- void tcp_arg(struct tcp_pcb *pcb, void *arg)
Specifies the program specific state that should be passed to all
other callback functions. The "pcb" argument is the current TCP
connection control block, and the "arg" argument is the argument
that will be passed to the callbacks.
--- TCP connection setup
The functions used for setting up connections is similar to that of
the sequential API and of the BSD socket API. A new TCP connection
identifier (i.e., a protocol control block - PCB) is created with the
tcp_new() function. This PCB can then be either set to listen for new
incoming connections or be explicitly connected to another host.
- struct tcp_pcb *tcp_new(void)
Creates a new connection identifier (PCB). If memory is not
available for creating the new pcb, NULL is returned.
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local IP address and port number. The IP address
can be specified as IP_ADDR_ANY in order to bind the connection to
all local IP addresses.
If another connection is bound to the same port, the function will
return ERR_USE, otherwise ERR_OK is returned.
- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
Commands a pcb to start listening for incoming connections. When an
incoming connection is accepted, the function specified with the
tcp_accept() function will be called. The pcb will have to be bound
to a local port with the tcp_bind() function.
The tcp_listen() function returns a new connection identifier, and
the one passed as an argument to the function will be
deallocated. The reason for this behavior is that less memory is
needed for a connection that is listening, so tcp_listen() will
reclaim the memory needed for the original connection and allocate a
new smaller memory block for the listening connection.
tcp_listen() may return NULL if no memory was available for the
listening connection. If so, the memory associated with the pcb
passed as an argument to tcp_listen() will not be deallocated.
- void tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
err_t err))
Specified the callback function that should be called when a new
connection arrives on a listening connection.
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port, err_t (* connected)(void *arg,
struct tcp_pcb *tpcb,
err_t err));
Sets up the pcb to connect to the remote host and sends the
initial SYN segment which opens the connection.
The tcp_connect() function returns immediately; it does not wait for
the connection to be properly setup. Instead, it will call the
function specified as the fourth argument (the "connected" argument)
when the connection is established. If the connection could not be
properly established, either because the other host refused the
connection or because the other host didn't answer, the "connected"
function will be called with an the "err" argument set accordingly.
The tcp_connect() function can return ERR_MEM if no memory is
available for enqueueing the SYN segment. If the SYN indeed was
enqueued successfully, the tcp_connect() function returns ERR_OK.
--- Sending TCP data
TCP data is sent by enqueueing the data with a call to
tcp_write(). When the data is successfully transmitted to the remote
host, the application will be notified with a call to a specified
callback function.
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
u8_t copy)
Enqueues the data pointed to by the argument dataptr. The length of
the data is passed as the len parameter. The copy argument is either
0 or 1 and indicates whether the new memory should be allocated for
the data to be copied into. If the argument is 0, no new memory
should be allocated and the data should only be referenced by
pointer.
The tcp_write() function will fail and return ERR_MEM if the length
of the data exceeds the current send buffer size or if the length of
the queue of outgoing segment is larger than the upper limit defined
in lwipopts.h. The number of bytes available in the output queue can
be retrieved with the tcp_sndbuf() function.
The proper way to use this function is to call the function with at
most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
the application should wait until some of the currently enqueued
data has been successfully received by the other host and try again.
- void tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
u16_t len))
Specifies the callback function that should be called when data has
successfully been received (i.e., acknowledged) by the remote
host. The len argument passed to the callback function gives the
amount bytes that was acknowledged by the last acknowledgment.
--- Receiving TCP data
TCP data reception is callback based - an application specified
callback function is called when new data arrives. When the
application has taken the data, it has to call the tcp_recved()
function to indicate that TCP can advertise increase the receive
window.
- void tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err))
Sets the callback function that will be called when new data
arrives. The callback function will be passed a NULL pbuf to
indicate that the remote host has closed the connection.
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
Must be called when the application has received the data. The len
argument indicates the length of the received data.
--- Application polling
When a connection is idle (i.e., no data is either transmitted or
received), lwIP will repeatedly poll the application by calling a
specified callback function. This can be used either as a watchdog
timer for killing connections that have stayed idle for too long, or
as a method of waiting for memory to become available. For instance,
if a call to tcp_write() has failed because memory wasn't available,
the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while.
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
Specifies the polling interval and the callback function that should
be called to poll the application. The interval is specified in
number of TCP coarse grained timer shots, which typically occurs
twice a second. An interval of 10 means that the application would
be polled every 5 seconds.
--- Closing and aborting connections
- err_t tcp_close(struct tcp_pcb *pcb)
Closes the connection. The function may return ERR_MEM if no memory
was available for closing the connection. If so, the application
should wait and try again either by using the acknowledgment
callback or the polling functionality. If the close succeeds, the
function returns ERR_OK.
The pcb is deallocated by the TCP code after a call to tcp_close().
- void tcp_abort(struct tcp_pcb *pcb)
Aborts the connection by sending a RST (reset) segment to the remote
host. The pcb is deallocated. This function never fails.
If a connection is aborted because of an error, the application is
alerted of this event by the err callback. Errors that might abort a
connection are when there is a shortage of memory. The callback
function to be called is set using the tcp_err() function.
- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
err_t err))
The error callback function does not get the pcb passed to it as a
parameter since the pcb may already have been deallocated.
--- Lower layer TCP interface
TCP provides a simple interface to the lower layers of the
system. During system initialization, the function tcp_init() has
to be called before any other TCP function is called. When the system
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
must be called with regular intervals. The tcp_fasttmr() should be
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
--- UDP interface
The UDP interface is similar to that of TCP, but due to the lower
level of complexity of UDP, the interface is significantly simpler.
- struct udp_pcb *udp_new(void)
Creates a new UDP pcb which can be used for UDP communication. The
pcb is not active until it has either been bound to a local address
or connected to a remote address.
- void udp_remove(struct udp_pcb *pcb)
Removes and deallocates the pcb.
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local address. The IP-address argument "ipaddr"
can be IP_ADDR_ANY to indicate that it should listen to any local IP
address. The function currently always return ERR_OK.
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Sets the remote end of the pcb. This function does not generate any
network traffic, but only set the remote address of the pcb.
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
Sends the pbuf p. The pbuf is not deallocated.
- void udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb,
struct pbuf *p,
struct ip_addr *addr,
u16_t port),
void *recv_arg)
Specifies a callback function that should be called when a UDP
datagram is received.

View File

@@ -1,120 +0,0 @@
Daily Use Guide for using Savannah for lwIP
Table of Contents:
1 - Obtaining lwIP from the Git repository
2 - Committers/developers Git access using SSH
3 - Merging a development branch to master branch
4 - How to release lwIP
1 Obtaining lwIP from the Git repository
----------------------------------------
To perform an anonymous Git clone of the master branch (this is where
bug fixes and incremental enhancements occur), do this:
git clone git://git.savannah.nongnu.org/lwip.git
Or, obtain a stable branch (updated with bug fixes only) as follows:
git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git
Or, obtain a specific (fixed) release as follows:
git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
2 Committers/developers Git access using SSH
--------------------------------------------
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
As such, Git commits to the server occur through a SSH tunnel for project members.
To create a SSH2 key pair in UNIX-like environments, do this:
ssh-keygen
Under Windows, a recommended SSH client is "PuTTY", freely available with good
documentation and a graphic user interface. Use its key generator.
Now paste the id_rsa.pub contents into your Savannah account public key list. Wait
a while so that Savannah can update its configuration (This can take minutes).
Try to login using SSH:
ssh -v your_login@git.sv.gnu.org
If it tells you:
Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686
Interactive shell login is not possible for security reasons.
VCS commands are allowed.
Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
You tried to execute:
Sorry, you are not allowed to execute that command.
Shared connection to git.sv.gnu.org closed.
then you could login; Savannah refuses to give you a shell - which is OK, as we
are allowed to use SSH for Git only. Now, you should be able to do this:
git clone your_login@git.sv.gnu.org:/srv/git/lwip.git
After which you can edit your local files with bug fixes or new features and
commit them. Make sure you know what you are doing when using Git to make
changes on the repository. If in doubt, ask on the lwip-members mailing list.
(If SSH asks about authenticity of the host, you can check the key
fingerprint against https://savannah.nongnu.org/git/?group=lwip
3 - Merging a development branch to master branch
-------------------------------------------------
Merging is a straightforward process in Git. How to merge all changes in a
development branch since our last merge from main:
Checkout the master branch:
git checkout master
Merge the development branch to master:
git merge your-development-branch
Resolve any conflict.
Commit the merge result.
git commit -a
Push your commits:
git push
4 How to release lwIP
---------------------
First, tag the release using Git: (I use release number 1.4.1 throughout
this example).
git tag -a STABLE-1_4_1
Share the tag reference by pushing it to remote:
git push origin STABLE-1_4_1
Prepare the release:
cp -r lwip lwip-1.4.1
rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes
Archive the current directory using tar, gzip'd, bzip2'd and zip'd.
tar czvf lwip-1.4.1.tar.gz lwip-1.4.1
tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1
zip -r lwip-1.4.1.zip lwip-1.4.1
Now, sign the archives with a detached GPG binary signature as follows:
gpg -b lwip-1.4.1.tar.gz
gpg -b lwip-1.4.1.tar.bz2
gpg -b lwip-1.4.1.zip
Upload these files using anonymous FTP:
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
ncftp> mput *1.4.1.*
Additionally, you may post a news item on Savannah, like this:
A new 1.4.1 release is now available here:
http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
You will have to submit this via the user News interface, then approve
this via the Administrator News interface.

125
doc/sys_arch.txt Normal file
View File

@@ -0,0 +1,125 @@
sys_arch interface for lwIP 0.5
Author: Adam Dunkels
$Id: sys_arch.txt,v 1.1.1.1 2002/10/19 12:59:33 likewise Exp $
The operating system emulation layer provides a common interface
between the lwIP code and the underlying operating system kernel. The
general idea is that porting lwIP to new architectures requires only
small changes to a few header files and a new sys_arch
implementation. It is also possible to do a sys_arch implementation
that does not rely on any underlying operating system.
The sys_arch provides semaphores and mailboxes to lwIP. For the full
lwIP functionality, multiple threads support can be implemented in the
sys_arch, but this is not required for the basic lwIP
functionality. Previous versions of lwIP required the sys_arch to
implement timer scheduling as well but as of lwIP 0.5 this is
implemented in a higher layer.
Semaphores can be either counting or binary - lwIP works with both
kinds. Mailboxes are used for message passing and can be implemented
either as a queue which allows multiple messages to be posted to a
mailbox, or as a rendez-vous point where only one message can be
posted at a time. lwIP works with both kinds, but the former type will
be more efficient. A message in a mailbox is just a pointer, nothing
more.
Semaphores are represented by the type "sys_sem_t" which is typedef'd
in the sys_arch.h file. Mailboxes are equivalently represented by the
type "sys_mbox_t". lwIP does not place any restrictions on how
sys_sem_t or sys_mbox_t are represented internally.
The following functions must be implemented by the sys_arch:
- void sys_init(void)
Is called to initialize the sys_arch layer.
- sys_sem_t sys_sem_new(u8_t count)
Creates and returns a new semaphore. The "count" argument specifies
the initial state of the semaphore.
- void sys_sem_free(sys_sem_t sem)
Deallocates a semaphore.
- void sys_sem_signal(sys_sem_t sem)
Signals a semaphore.
- u16_t sys_arch_sem_wait(sys_sem_t sem, u16_t timeout)
Blocks the thread while waiting for the semaphore to be
signaled. If the "timeout" argument is non-zero, the thread should
only be blocked for the specified time (measured in
milliseconds).
If the timeout argument is non-zero, the return value is the amount
of time spent waiting for the semaphore to be signaled. If the
semaphore wasn't signaled within the specified time, the return
value is zero. If the thread didn't have to wait for the semaphore
(i.e., it was already signaled), care must be taken to ensure that
the function does not return a zero value since this is used to
indicate that a timeout occured. A suitable way to implement this is
to check if the time spent waiting is zero and if so, the value 1 is
returned.
Notice that lwIP implements a function with a similar name,
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
- sys_mbox_t sys_mbox_new(void)
Creates an empty mailbox.
- void sys_mbox_free(sys_mbox_t mbox)
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
programming error in lwIP and the developer should be notified.
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
Posts the "msg" to the mailbox.
- u16_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u16_t timeout)
Blocks the thread until a message arrives in the mailbox, but does
not block the thread longer than "timeout" milliseconds (similar to
the sys_arch_sem_wait() function). The "msg" argument is a result
parameter that is set by the function (i.e., by doing "*msg =
ptr"). The "msg" parameter maybe NULL to indicate that the message
should be dropped.
The return values are the same as for the sys_arch_sem_wait()
function and the function must not return zero even if a message was
present in the mailbox and the time spent waiting was zero
milliseconds.
Note that a function with a similar name, sys_mbox_fetch(), is
implemented by lwIP.
- struct sys_timeouts *sys_arch_timeouts(void)
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
each thread has a list of timeouts which is repressented as a linked
list of sys_timeout structures. The sys_timeouts structure holds a
pointer to a linked list of timeouts. This function is called by
the lwIP timeout scheduler and must not return a NULL value.
In a single threadd sys_arch implementation, this function will
simply return a pointer to a global sys_timeouts variable stored in
the sys_arch module.
If threads are supported by the underlying operating system and if
such functionality is needed in lwIP, the following function will have
to be implemented as well:
- void sys_thread_new(void (* thread)(void *arg), void *arg)
Starts a new thread that will begin its execution in the function
"thread()". The "arg" argument will be passed as an argument to the
thread() function.

View File

@@ -1,5 +0,0 @@
{
"name": "library-lwip",
"version": "2.1.3-bdk",
"description": "lwIP - A Lightweight TCPIP stack"
}

View File

@@ -1,111 +0,0 @@
/*
* cc.h - Architecture environment, some compiler specific, some
* environment specific (probably should move env stuff
* to sys_arch.h.)
*
* Typedefs for the types used by lwip -
* u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
*
* Compiler hints for packing lwip's structures -
* PACK_STRUCT_FIELD(x)
* PACK_STRUCT_STRUCT
* PACK_STRUCT_BEGIN
* PACK_STRUCT_END
*
* Platform specific diagnostic output -
* LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
* LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
* Portability defines for printf formatters:
* U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
*
* "lightweight" synchronization mechanisms -
* SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
* SYS_ARCH_PROTECT(x) - enter protection mode.
* SYS_ARCH_UNPROTECT(x) - leave protection mode.
*
* If the compiler does not provide memset() this file must include a
* definition of it, or include a file which defines it.
*
* This file must either include a system-local <errno.h> which defines
* the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
* to make lwip/arch.h define the codes which are used throughout.
*/
#ifndef __CC_H__
#define __CC_H__
#include "typedef.h"
#include "uart_pub.h"
/*
* Typedefs for the types used by lwip -
* u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
*/
typedef unsigned char u8_t; /* Unsigned 8 bit quantity */
typedef signed char s8_t; /* Signed 8 bit quantity */
typedef unsigned short u16_t; /* Unsigned 16 bit quantity */
typedef signed short s16_t; /* Signed 16 bit quantity */
typedef unsigned long u32_t; /* Unsigned 32 bit quantity */
typedef signed long s32_t; /* Signed 32 bit quantity */
//typedef unsigned long mem_ptr_t; /* Unsigned 32 bit quantity */
typedef int intptr_t;
typedef unsigned int uintptr_t;
typedef int sys_prot_t;
#if defined(__GNUC__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_FIELD(x) x
#elif defined(__ICCARM__)
#define PACK_STRUCT_BEGIN __packed
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_FIELD(x) x
#else
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_FIELD(x) x
#endif
/*
* Platform specific diagnostic output -
* LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
* LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
* Portability defines for printf formatters:
* U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
*/
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) \
do \
{ fatal_prf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \
} while(0)
#endif
#ifndef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {fatal_prf x ;} while(0)
#endif
#define U16_F "4d"
#define S16_F "4d"
#define X16_F "4x"
#define U32_F "8ld"
#define S32_F "8ld"
#define X32_F "8lx"
/*
* unknow defination
*/
// cup byte order
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
extern int bk_rand(); /* FIXME: move to right place */
#define LWIP_RAND() ((uint32_t)bk_rand())
#endif
// eof

View File

@@ -1,335 +0,0 @@
/**
* @file
* Ethernet Interface Skeleton
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*/
#include "include.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include "ethernetif.h"
#include <stdio.h>
#include <string.h>
#include "netif/etharp.h"
#include "lwip_netif_address.h"
#include "sa_station.h"
#include "drv_model_pub.h"
#include "mem_pub.h"
#include "common.h"
#include "hostapd_cfg.h"
#include "sk_intf.h"
#include "rw_pub.h"
#include "rtos_pub.h"
#include "param_config.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
#include "uart_pub.h"
#define ETH_INTF_DEBUG
#ifdef ETH_INTF_DEBUG
#define ETH_INTF_PRT warning_prf
#define ETH_INTF_WARN warning_prf
#define ETH_INTF_FATAL fatal_prf
#else
#define ETH_INTF_PRT null_prf
#define ETH_INTF_WARN null_prf
#define ETH_INTF_FATAL null_prf
#endif
extern int bmsg_tx_sender(struct pbuf *p, uint32_t vif_idx);
/* Forward declarations. */
void ethernetif_input(int iface, struct pbuf *p);
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
const char wlan_name[][6] =
{
"wlan0\0",
"wlan1\0",
"wlan2\0",
"wlan3\0",
};
static void low_level_init(struct netif *netif)
{
VIF_INF_PTR vif_entry = (VIF_INF_PTR)(netif->state);
u8 *macptr = (u8*)&vif_entry->mac_addr;
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = (char*)&wlan_name[vif_entry->index];
#endif /* LWIP_NETIF_HOSTNAME */
//wifi_get_mac_address((char *)wireless_mac, type);
/* set MAC hardware address length */
ETH_INTF_PRT("enter low level!\r\n");
ETH_INTF_PRT("mac %2x:%2x:%2x:%2x:%2x:%2x\r\n", macptr[0], macptr[1], macptr[2],
macptr[3], macptr[4], macptr[5]);
netif->hwaddr_len = ETHARP_HWADDR_LEN;
os_memcpy(netif->hwaddr, macptr, ETHARP_HWADDR_LEN);
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
ETH_INTF_PRT("leave low level!\r\n");
}
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
int ret;
err_t err = ERR_OK;
uint8_t vif_idx = rwm_mgmt_get_netif2vif(netif);
//os_printf("output:%x\r\n", p);
ret = bmsg_tx_sender(p, (uint32_t)vif_idx);
if(0 != ret)
{
err = ERR_TIMEOUT;
}
return err;
}
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void
ethernetif_input(int iface, struct pbuf *p)
{
struct eth_hdr *ethhdr;
struct netif *netif;
if (p->len <= SIZEOF_ETH_HDR) {
pbuf_free(p);
return;
}
netif = rwm_mgmt_get_vif2netif((uint8_t)iface);
if(!netif) {
//ETH_INTF_PRT("ethernetif_input no netif found %d\r\n", iface);
pbuf_free(p);
p = NULL;
return;
}
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
switch (htons(ethhdr->type))
{
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (netif->input(p, netif) != ERR_OK) // ethernet_input
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\r\n"));
pbuf_free(p);
p = NULL;
}
break;
case ETHTYPE_EAPOL:
ke_l2_packet_tx(p->payload, p->len, iface);
pbuf_free(p);
p = NULL;
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t
ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netifapi_netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t lwip_netif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;
#ifdef CONFIG_IPV6
netif->output_ip6 = ethip6_output;
#endif
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
err_t lwip_netif_uap_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
//netif->state = NULL;
netif->name[0] = 'u';
netif->name[1] = 'a';
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
// eof

View File

@@ -1,13 +0,0 @@
#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__
#include "lwip/err.h"
#include "lwip/netif.h"
void ethernetif_recv(struct netif *netif, int total_len);
err_t ethernetif_init(struct netif *netif);
#endif

View File

@@ -1,17 +0,0 @@
#ifndef __LWIP_INTF_H__
#define __LWIP_INTF_H__
#define LWIP_INTF_DEBUG
#ifdef LWIP_INTF_DEBUG
#define LWIP_INTF_PRT warning_prf
#define LWIP_INTF_WARN warning_prf
#define LWIP_INTF_FATAL fatal_prf
#else
#define LWIP_INTF_PRT null_prf
#define LWIP_INTF_WARN null_prf
#define LWIP_INTF_FATAL null_prf
#endif
#endif
// eof

View File

@@ -1,48 +0,0 @@
#ifndef _MXCHIP_NETIF_ADDR_H_
#define _MXCHIP_NETIF_ADDR_H_
/** MLAN BSS type */
typedef enum _wifi_interface_type
{
WIFI_INTERFACE_TYPE_STA = 0,
WIFI_INTERFACE_TYPE_UAP = 1,
WIFI_INTERFACE_TYPE_ANY = 0xff,
} wifi_interface_type;
#define ADDR_TYPE_STATIC 1
#define ADDR_TYPE_DHCP 0
/** This data structure represents an IPv4 address */
struct ipv4_config {
/** DHCP_Disable DHCP_Client DHCP_Server */
unsigned addr_type;
/** The system's IP address in network order. */
unsigned address;
/** The system's default gateway in network order. */
unsigned gw;
/** The system's subnet mask in network order. */
unsigned netmask;
/** The system's primary dns server in network order. */
unsigned dns1;
/** The system's secondary dns server in network order. */
unsigned dns2;
};
/** Network IP configuration.
*
* This data structure represents the network IP configuration
* for IPv4 as well as IPv6 addresses
*/
struct wlan_ip_config {
#ifdef CONFIG_IPV6
/** The network IPv6 address configuration that should be
* associated with this interface. */
struct ipv6_config ipv6[MAX_IPV6_ADDRESSES];
#endif
/** The network IPv4 address configuration that should be
* associated with this interface. */
struct ipv4_config ipv4;
};
#endif

View File

@@ -1,461 +0,0 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
#include "sys_config.h"
/**
* Loopback demo related options.
*/
#define LWIP_NETIF_LOOPBACK 1
#define LWIP_HAVE_LOOPIF 1
#define LWIP_NETIF_LOOPBACK_MULTITHREADING 1
#define LWIP_LOOPBACK_MAX_PBUFS 8
#define TCPIP_THREAD_NAME "tcp/ip"
#define TCPIP_THREAD_STACKSIZE 512
#define TCPIP_THREAD_PRIO 7
#define DEFAULT_THREAD_STACKSIZE 200
#define DEFAULT_THREAD_PRIO 1
/* Disable lwIP asserts */
#define LWIP_NOASSERT 1
#define LWIP_DEBUG 0
#define LWIP_DEBUG_TRACE 0
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define IGMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#define AUTOIP_DEBUG LWIP_DBG_OFF
#define SNMP_MSG_DEBUG LWIP_DBG_OFF
#define SNMP_MIB_DEBUG LWIP_DBG_OFF
#define DNS_DEBUG LWIP_DBG_OFF
//#define LWIP_COMPAT_MUTEX 1
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT 1
/*
------------------------------------
---------- Memory options ----------
------------------------------------
*/
/**
* MEM_ALIGNMENT: should be set to the alignment of the CPU
* 4 byte alignment -> #define MEM_ALIGNMENT 4
* 2 byte alignment -> #define MEM_ALIGNMENT 2
*/
#define MEM_ALIGNMENT 4
#define MAX_SOCKETS_TCP 12
#define MAX_LISTENING_SOCKETS_TCP 4
#define MAX_SOCKETS_UDP 22
#define TCP_SND_BUF_COUNT 5
/* Value of TCP_SND_BUF_COUNT denotes the number of buffers and is set by
* CONFIG option available in the SDK
*/
/* Buffer size needed for TCP: Max. number of TCP sockets * Size of pbuf *
* Max. number of TCP sender buffers per socket
*
* Listening sockets for TCP servers do not require the same amount buffer
* space. Hence do not consider these sockets for memory computation
*/
#define TCP_MEM_SIZE (MAX_SOCKETS_TCP * \
PBUF_POOL_BUFSIZE * (TCP_SND_BUF/TCP_MSS))
/* Buffer size needed for UDP: Max. number of UDP sockets * Size of pbuf
*/
#define UDP_MEM_SIZE (MAX_SOCKETS_UDP * PBUF_POOL_BUFSIZE)
/**
* MEM_SIZE: the size of the heap memory. If the application will send
* a lot of data that needs to be copied, this should be set high.
*/
#if ((defined(CFG_LWIP_MEM_POLICY))&&(CFG_LWIP_MEM_POLICY == LWIP_REDUCE_THE_PLAN))
#define MEM_SIZE (16*1024)
#else
#define MEM_SIZE (32*1024)
#endif
/*
------------------------------------------------
---------- Internal Memory Pool Sizes ----------
------------------------------------------------
*/
/**
* MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF).
* If the application sends a lot of data out of ROM (or other static memory),
* this should be set high.
*/
#define MEMP_NUM_PBUF 10
/**
* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
* (requires the LWIP_TCP option)
*/
#define MEMP_NUM_TCP_PCB MAX_SOCKETS_TCP
#define MEMP_NUM_TCP_PCB_LISTEN MAX_LISTENING_SOCKETS_TCP
/**
* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
* (requires the LWIP_TCP option)
*/
//#define MEMP_NUM_TCP_SEG 12
/**
* MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
* for incoming packets.
* (only needed if you use tcpip.c)
*/
#define MEMP_NUM_TCPIP_MSG_INPKT 16
/**
* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
* (requires NO_SYS==0)
*/
#define MEMP_NUM_SYS_TIMEOUT 12
/**
* MEMP_NUM_NETBUF: the number of struct netbufs.
* (only needed if you use the sequential API, like api_lib.c)
*/
#define MEMP_NUM_NETBUF 16
/**
* MEMP_NUM_NETCONN: the number of struct netconns.
* (only needed if you use the sequential API, like api_lib.c)
*
* This number corresponds to the maximum number of active sockets at any
* given point in time. This number must be sum of max. TCP sockets, max. TCP
* sockets used for listening, and max. number of UDP sockets
*/
#define MEMP_NUM_NETCONN (MAX_SOCKETS_TCP + \
MAX_LISTENING_SOCKETS_TCP + MAX_SOCKETS_UDP)
/**
* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
*/
#if ((defined(CFG_LWIP_MEM_POLICY))&&(CFG_LWIP_MEM_POLICY == LWIP_REDUCE_THE_PLAN))
#define PBUF_POOL_SIZE 3
#else
#define PBUF_POOL_SIZE 10
#endif
/*
----------------------------------
---------- Pbuf options ----------
----------------------------------
*/
/**
* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
* designed to accomodate single full size TCP frame in one pbuf, including
* TCP_MSS, IP header, and link header.
*/
#define PBUF_POOL_BUFSIZE 1580
/*
---------------------------------
---------- RAW options ----------
---------------------------------
*/
/**
* LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
*/
#define LWIP_RAW 1
#ifdef CONFIG_IPV6
#define LWIP_IPV6 1
#endif
/* Enable IPv4 Auto IP */
#ifdef CONFIG_AUTOIP
#define LWIP_AUTOIP 1
#define LWIP_DHCP_AUTOIP_COOP 1
#define LWIP_DHCP_AUTOIP_COOP_TRIES 5
#endif
/*
------------------------------------
---------- Socket options ----------
------------------------------------
*/
/**
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
*/
#define LWIP_SOCKET 1
#define LWIP_NETIF_API 1
/**
* LWIP_RECV_CB==1: Enable callback when a socket receives data.
*/
#define LWIP_RECV_CB 1
/**
* SO_REUSE==1: Enable SO_REUSEADDR option.
*/
#define SO_REUSE 1
#define SO_REUSE_RXTOALL 1
/**
* Enable TCP_KEEPALIVE
*/
#define LWIP_TCP_KEEPALIVE 1
/*
----------------------------------------
---------- Statistics options ----------
----------------------------------------
*/
/**
* LWIP_STATS==1: Enable statistics collection in lwip_stats.
*/
#define LWIP_STATS 1
/**
* LWIP_STATS_DISPLAY==1: Compile in the statistics output functions.
*/
#define LWIP_STATS_DISPLAY 0
/*
----------------------------------
---------- DHCP options ----------
----------------------------------
*/
/**
* LWIP_DHCP==1: Enable DHCP module.
*/
#define LWIP_DHCP 1
#define LWIP_NETIF_STATUS_CALLBACK 1
/**
* DNS related options, revisit later to fine tune.
*/
#define LWIP_DNS 1
#define DNS_TABLE_SIZE 2 // number of table entries, default 4
//#define DNS_MAX_NAME_LENGTH 64 // max. name length, default 256
#define DNS_MAX_SERVERS 2 // number of DNS servers, default 2
#define DNS_DOES_NAME_CHECK 1 // compare received name with given,def 0
#define DNS_MSG_SIZE 512
#define MDNS_MSG_SIZE 512
#define MDNS_TABLE_SIZE 1 // number of mDNS table entries
#define MDNS_MAX_SERVERS 1 // number of mDNS multicast addresses
/* TODO: Number of active UDP PCBs is equal to number of active UDP sockets plus
* two. Need to find the users of these 2 PCBs
*/
#define MEMP_NUM_UDP_PCB (MAX_SOCKETS_UDP + 2)
/* NOTE: some times the socket() call for SOCK_DGRAM might fail if you dont
* have enough MEMP_NUM_UDP_PCB */
/*
----------------------------------
---------- IGMP options ----------
----------------------------------
*/
/**
* LWIP_IGMP==1: Turn on IGMP module.
*/
#define LWIP_IGMP 1
/**
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
* SO_SNDTIMEO processing.
*/
#define LWIP_SO_SNDTIMEO 1
/**
* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
* SO_RCVTIMEO processing.
*/
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_SNDTIMEO 1
/**
* TCP_LISTEN_BACKLOG==1: Handle backlog connections.
*/
#define TCP_LISTEN_BACKLOG 1
#define LWIP_PROVIDE_ERRNO 1
#include <errno.h>
#define ERRNO 1
//#define LWIP_SNMP 1
/*
------------------------------------------------
---------- Network Interfaces options ----------
------------------------------------------------
*/
/**
* LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
* field.
*/
#define LWIP_NETIF_HOSTNAME 1
/*
The STM32F107 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
- To use this feature let the following define uncommented.
- To disable it and process by CPU comment the the checksum.
*/
//#define CHECKSUM_BY_HARDWARE
#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
#else
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 1
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 1
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 1
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 1
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
#endif
/**
* TCP_RESOURCE_FAIL_RETRY_LIMIT: limit for retrying sending of tcp segment
* on resource failure error returned by driver.
*/
#define TCP_RESOURCE_FAIL_RETRY_LIMIT 50
//#ifdef CONFIG_ENABLE_MXCHIP
/* save memory */
#if ((defined(CFG_LWIP_MEM_POLICY))&&(CFG_LWIP_MEM_POLICY == LWIP_REDUCE_THE_PLAN))
#define TCP_MSS (1500 - 40)
/* TCP receive window. */
#define TCP_WND (3 * TCP_MSS)
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (10*TCP_MSS)
#define TCP_SND_QUEUELEN (20)
#else
#define TCP_MSS (1500 - 40)
/* TCP receive window. */
#define TCP_WND (10*TCP_MSS)
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (10*TCP_MSS)
#define TCP_SND_QUEUELEN (20)
#endif
/* ARP before DHCP causes multi-second delay - turn it off */
#define DHCP_DOES_ARP_CHECK (0)
#define TCP_MAX_ACCEPT_CONN 5
#define MEMP_NUM_TCP_SEG (TCP_SND_QUEUELEN*2)
#define IP_REASS_MAX_PBUFS 0
#define IP_REASSEMBLY 0
#define IP_REASS_MAX_PBUFS 0
#define IP_REASSEMBLY 0
#define MEMP_NUM_REASSDATA 0
#define IP_FRAG 0
#define MEM_LIBC_MALLOC (0)
#define DEFAULT_UDP_RECVMBOX_SIZE 3 //each udp socket max buffer 3 packets.
#define MEMP_MEM_MALLOC (0)
#define TCP_MSL (TCP_TMR_INTERVAL)
#define LWIP_COMPAT_MUTEX_ALLOWED (1)
#define MEMP_STATS 1
#define MEM_STATS 1
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
#define LWIP_RIPPLE20 1
/* Beken specific LWIP options */
#define BK_DHCP 1
#endif /* __LWIPOPTS_H__ */

View File

@@ -1,797 +0,0 @@
#include "include.h"
#include <stdio.h>
#include <string.h>
#include <lwip/inet.h>
#include "netif/etharp.h"
#include "lwip/netif.h"
#include <lwip/netifapi.h>
#include <lwip/tcpip.h>
#include <lwip/dns.h>
#include <lwip/dhcp.h>
#include "lwip/prot/dhcp.h"
#include <lwip/sockets.h>
#include "ethernetif.h"
#include "sa_station.h"
#include "drv_model_pub.h"
#include "mem_pub.h"
#include "common.h"
#include "rw_pub.h"
#include "lwip_netif_address.h"
#include "rtos_pub.h"
#include "net.h"
#if CFG_ROLE_LAUNCH
#include "role_launch.h"
#endif
/* forward declaration */
FUNC_1PARAM_PTR bk_wlan_get_status_cb(void);
struct ipv4_config sta_ip_settings;
struct ipv4_config uap_ip_settings;
static int up_iface;
uint32_t sta_ip_start_flag = 0;
uint32_t uap_ip_start_flag = 0;
#ifdef CONFIG_IPV6
#define IPV6_ADDR_STATE_TENTATIVE "Tentative"
#define IPV6_ADDR_STATE_PREFERRED "Preferred"
#define IPV6_ADDR_STATE_INVALID "Invalid"
#define IPV6_ADDR_STATE_VALID "Valid"
#define IPV6_ADDR_STATE_DEPRECATED "Deprecated"
#define IPV6_ADDR_TYPE_LINKLOCAL "Link-Local"
#define IPV6_ADDR_TYPE_GLOBAL "Global"
#define IPV6_ADDR_TYPE_UNIQUELOCAL "Unique-Local"
#define IPV6_ADDR_TYPE_SITELOCAL "Site-Local"
#define IPV6_ADDR_UNKNOWN "Unknown"
#endif
#define net_e warning_prf
#define net_d warning_prf
typedef void (*net_sta_ipup_cb_fn)(void* data);
struct interface {
struct netif netif;
ip_addr_t ipaddr;
ip_addr_t nmask;
ip_addr_t gw;
};
FUNCPTR sta_connected_func;
static struct interface g_mlan = {{0}};
static struct interface g_uap = {{0}};
net_sta_ipup_cb_fn sta_ipup_cb = NULL;
extern void *net_get_sta_handle(void);
extern void *net_get_uap_handle(void);
extern err_t lwip_netif_init(struct netif *netif);
extern err_t lwip_netif_uap_init(struct netif *netif);
extern int net_get_if_ip_addr(uint32_t *ip, void *intrfc_handle);
extern int net_get_if_ip_mask(uint32_t *nm, void *intrfc_handle);
extern int net_configure_address(struct ipv4_config *addr, void *intrfc_handle);
extern int dhcp_server_start(void *intrfc_handle);
extern void dhcp_server_stop(void);
extern void net_configure_dns(struct wlan_ip_config *ip);
#ifdef CONFIG_IPV6
char *ipv6_addr_state_to_desc(unsigned char addr_state)
{
if (ip6_addr_istentative(addr_state))
return IPV6_ADDR_STATE_TENTATIVE;
else if (ip6_addr_ispreferred(addr_state))
return IPV6_ADDR_STATE_PREFERRED;
else if (ip6_addr_isinvalid(addr_state))
return IPV6_ADDR_STATE_INVALID;
else if (ip6_addr_isvalid(addr_state))
return IPV6_ADDR_STATE_VALID;
else if (ip6_addr_isdeprecated(addr_state))
return IPV6_ADDR_STATE_DEPRECATED;
else
return IPV6_ADDR_UNKNOWN;
}
char *ipv6_addr_type_to_desc(struct ipv6_config *ipv6_conf)
{
if (ip6_addr_islinklocal((ip6_addr_t *)ipv6_conf->address))
return IPV6_ADDR_TYPE_LINKLOCAL;
else if (ip6_addr_isglobal((ip6_addr_t *)ipv6_conf->address))
return IPV6_ADDR_TYPE_GLOBAL;
else if (ip6_addr_isuniquelocal((ip6_addr_t *)ipv6_conf->address))
return IPV6_ADDR_TYPE_UNIQUELOCAL;
else if (ip6_addr_issitelocal((ip6_addr_t *)ipv6_conf->address))
return IPV6_ADDR_TYPE_SITELOCAL;
else
return IPV6_ADDR_UNKNOWN;
}
#endif /* CONFIG_IPV6 */
int net_dhcp_hostname_set(char *hostname)
{
netif_set_hostname(&g_mlan.netif, hostname);
return 0;
}
void net_ipv4stack_init(void)
{
static bool tcpip_init_done = 0;
if (tcpip_init_done)
return;
net_d("Initializing TCP/IP stack\r\n");
tcpip_init(NULL, NULL);
tcpip_init_done = true;
}
#ifdef CONFIG_IPV6
void net_ipv6stack_init(struct netif *netif)
{
uint8_t mac[6];
netif->flags |= NETIF_IPV6_FLAG_UP;
/* Set Multicast filter for IPV6 link local address
* It contains first three bytes: 0x33 0x33 0xff (fixed)
* and last three bytes as last three bytes of device mac */
mac[0] = 0x33;
mac[1] = 0x33;
mac[2] = 0xff;
mac[3] = netif->hwaddr[3];
mac[4] = netif->hwaddr[4];
mac[5] = netif->hwaddr[5];
wifi_add_mcast_filter(mac);
netif_create_ip6_linklocal_address(netif, 1);
netif->ip6_autoconfig_enabled = 1;
/* IPv6 routers use multicast IPv6 ff02::1 and MAC address
33:33:00:00:00:01 for router advertisements */
mac[0] = 0x33;
mac[1] = 0x33;
mac[2] = 0x00;
mac[3] = 0x00;
mac[4] = 0x00;
mac[5] = 0x01;
wifi_add_mcast_filter(mac);
}
static void wm_netif_ipv6_status_callback(struct netif *n)
{
/* TODO: Implement appropriate functionality here*/
net_d("Received callback on IPv6 address state change");
wlan_wlcmgr_send_msg(WIFI_EVENT_NET_IPV6_CONFIG,
WIFI_EVENT_REASON_SUCCESS, NULL);
}
#endif /* CONFIG_IPV6 */
void net_wlan_init(void)
{
static int wlan_init_done = 0;
int ret;
if (!wlan_init_done) {
net_ipv4stack_init();
g_mlan.ipaddr.addr = INADDR_ANY;
ret = netifapi_netif_add(&g_mlan.netif, &g_mlan.ipaddr,
&g_mlan.ipaddr, &g_mlan.ipaddr, NULL,
lwip_netif_init, tcpip_input);
if (ret) {
/*FIXME: Handle the error case cleanly */
net_e("MLAN interface add failed");
}
#ifdef CONFIG_IPV6
net_ipv6stack_init(&g_mlan.netif);
#endif /* CONFIG_IPV6 */
ret = netifapi_netif_add(&g_uap.netif, &g_uap.ipaddr,
&g_uap.ipaddr, &g_uap.ipaddr, NULL,
lwip_netif_uap_init, tcpip_input);
if (ret) {
/*FIXME: Handle the error case cleanly */
net_e("UAP interface add failed");
}
wlan_init_done = 1;
}
return;
}
void net_set_sta_ipup_callback(void *fn)
{
sta_ipup_cb = (net_sta_ipup_cb_fn)fn;
}
void user_connected_callback(FUNCPTR fn)
{
sta_connected_func = fn;
}
static void wm_netif_status_static_callback(struct netif *n)
{
if (n->flags & NETIF_FLAG_UP)
{
// static IP success;
os_printf("using static ip...\n");
mhdr_set_station_status(RW_EVT_STA_GOT_IP);/* dhcp success*/
if(sta_ipup_cb != NULL)
sta_ipup_cb(NULL);
if(sta_connected_func != NULL)
(*sta_connected_func)();
}
else
{
// static IP fail;
}
}
static void wm_netif_status_callback(struct netif *n)
{
FUNC_1PARAM_PTR fn;
struct dhcp *dhcp;
u32 val;
if (n->flags & NETIF_FLAG_UP)
{
dhcp = netif_dhcp_data(n);
if(dhcp != NULL)
{
if (dhcp->state == DHCP_STATE_BOUND)
{
os_printf("ip_addr: %x\r\n", n->ip_addr.addr);
#if CFG_ROLE_LAUNCH
rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED);
#endif
fn = (FUNC_1PARAM_PTR)bk_wlan_get_status_cb();
if(fn)
{
val = RW_EVT_STA_GOT_IP;
(*fn)(&val);
}
mhdr_set_station_status(RW_EVT_STA_GOT_IP);
/* dhcp success*/
if(sta_ipup_cb != NULL)
sta_ipup_cb(NULL);
if(sta_connected_func != NULL)
(*sta_connected_func)();
}
else
{
// dhcp fail
}
}
else
{
// static IP success;
}
}
else
{
// dhcp fail;
}
}
static int check_iface_mask(void *handle, uint32_t ipaddr)
{
uint32_t interface_ip, interface_mask;
net_get_if_ip_addr(&interface_ip, handle);
net_get_if_ip_mask(&interface_mask, handle);
if (interface_ip > 0)
if ((interface_ip & interface_mask) ==
(ipaddr & interface_mask))
return 0;
return -1;
}
void *net_ip_to_interface(uint32_t ipaddr)
{
int ret;
void *handle;
/* Check mlan handle */
handle = net_get_sta_handle();
ret = check_iface_mask(handle, ipaddr);
if (ret == 0)
return handle;
/* Check uap handle */
handle = net_get_uap_handle();
ret = check_iface_mask(handle, ipaddr);
if (ret == 0)
return handle;
/* If more interfaces are added then above check needs to done for
* those newly added interfaces
*/
return NULL;
}
void *net_sock_to_interface(int sock)
{
struct sockaddr_in peer;
unsigned long peerlen = sizeof(struct sockaddr_in);
void *req_iface = NULL;
getpeername(sock, (struct sockaddr *)&peer, &peerlen);
req_iface = net_ip_to_interface(peer.sin_addr.s_addr);
return req_iface;
}
void *net_get_sta_handle(void)
{
return &g_mlan.netif;
}
void *net_get_uap_handle(void)
{
return &g_uap.netif;
}
void *net_get_netif_handle(uint8_t iface)
{
return NULL;
}
void net_interface_up(void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
netifapi_netif_set_up(&if_handle->netif);
}
void net_interface_down(void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
netifapi_netif_set_down(&if_handle->netif);
}
#ifdef CONFIG_IPV6
void net_interface_deregister_ipv6_callback(void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
if (intrfc_handle == &g_mlan)
netif_set_ipv6_status_callback(&if_handle->netif, NULL);
}
#endif
void net_interface_dhcp_stop(void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
netifapi_dhcp_stop(&if_handle->netif);
netif_set_status_callback(&if_handle->netif, NULL);
}
void sta_ip_down(void)
{
if(sta_ip_start_flag)
{
os_printf("sta_ip_down\r\n");
sta_ip_start_flag = 0;
netifapi_netif_set_down(&g_mlan.netif);
netif_set_status_callback(&g_mlan.netif, NULL);
netifapi_dhcp_stop(&g_mlan.netif);
}
}
void sta_ip_start(void)
{
struct wlan_ip_config address = {0};
if(!sta_ip_start_flag)
{
os_printf("sta_ip_start\r\n");
sta_ip_start_flag = 1;
net_configure_address(&sta_ip_settings, net_get_sta_handle());
return;
}
os_printf("sta_ip_start2:0x%x\r\n", address.ipv4.address);
net_get_if_addr(&address, net_get_sta_handle());
if((mhdr_get_station_status() == RW_EVT_STA_CONNECTED)
&& (0 != address.ipv4.address))
{
mhdr_set_station_status(RW_EVT_STA_GOT_IP);
}
}
void sta_set_vif_netif(void)
{
rwm_mgmt_set_vif_netif(&g_mlan.netif);
}
void ap_set_vif_netif(void)
{
rwm_mgmt_set_vif_netif(&g_uap.netif);
}
void sta_set_default_netif(void)
{
netifapi_netif_set_default(net_get_sta_handle());
}
void ap_set_default_netif(void)
{
// as the default netif is sta's netif, so ap need to send
// boardcast or not sub net packets, need set ap netif before
// send those packets, after finish sending, reset default netif
// to sat's netif.
netifapi_netif_set_default(net_get_uap_handle());
}
void reset_default_netif(void)
{
if (sta_ip_is_start()) {
netifapi_netif_set_default(net_get_sta_handle());
} else {
netifapi_netif_set_default(NULL);
}
}
uint32_t sta_ip_is_start(void)
{
return sta_ip_start_flag;
}
void uap_ip_down(void)
{
if (uap_ip_start_flag )
{
os_printf("uap_ip_down\r\n");
uap_ip_start_flag = 0;
netifapi_netif_set_down(&g_uap.netif);
netif_set_status_callback(&g_uap.netif, NULL);
dhcp_server_stop();
}
}
void uap_ip_start(void)
{
if ( !uap_ip_start_flag )
{
os_printf("uap_ip_start\r\n");
uap_ip_start_flag = 1;
net_configure_address(&uap_ip_settings, net_get_uap_handle());
}
}
uint32_t uap_ip_is_start(void)
{
return uap_ip_start_flag;
}
#define DEF_UAP_IP 0xc0a80a01UL /* 192.168.10.1 */
void ip_address_set(int iface, int dhcp, char *ip, char *mask, char*gw, char*dns)
{
uint32_t tmp;
struct ipv4_config addr;
memset(&addr, 0, sizeof(struct ipv4_config));
if (dhcp == 1) {
addr.addr_type = ADDR_TYPE_DHCP;
} else {
addr.addr_type = ADDR_TYPE_STATIC;
tmp = inet_addr((char*)ip);
addr.address = (tmp);
tmp = inet_addr((char*)mask);
if (tmp == 0xFFFFFFFF)
tmp = 0x00FFFFFF;// if not set valid netmask, set as 255.255.255.0
addr.netmask= (tmp);
tmp = inet_addr((char*)gw);
addr.gw = (tmp);
tmp = inet_addr((char*)dns);
addr.dns1 = (tmp);
}
if (iface == 1) // Station
memcpy(&sta_ip_settings, &addr, sizeof(addr));
else
memcpy(&uap_ip_settings, &addr, sizeof(addr));
}
int net_configure_address(struct ipv4_config *addr, void *intrfc_handle)
{
if (!intrfc_handle)
return -1;
struct interface *if_handle = (struct interface *)intrfc_handle;
net_d("\r\nconfiguring interface %s (with %s)",
(if_handle == &g_mlan) ? "mlan" :"uap",
(addr->addr_type == ADDR_TYPE_DHCP)
? "DHCP client" : "Static IP");
netifapi_netif_set_down(&if_handle->netif);
/* De-register previously registered DHCP Callback for correct
* address configuration.
*/
netif_set_status_callback(&if_handle->netif, NULL);
#ifdef CONFIG_IPV6
if (if_handle == &g_mlan) {
netif_set_ipv6_status_callback(&if_handle->netif,
wm_netif_ipv6_status_callback);
/* Explicitly call this function so that the linklocal address
* gets updated even if the interface does not get any IPv6
* address in its lifetime */
wm_netif_ipv6_status_callback(&if_handle->netif);
}
#endif
switch (addr->addr_type) {
case ADDR_TYPE_STATIC:
if_handle->ipaddr.addr = addr->address;
if_handle->nmask.addr = addr->netmask;
if_handle->gw.addr = addr->gw;
netifapi_netif_set_addr(&if_handle->netif, &if_handle->ipaddr,
&if_handle->nmask, &if_handle->gw);
netifapi_netif_set_up(&if_handle->netif);
net_configure_dns((struct wlan_ip_config *)addr);
if(if_handle == &g_mlan)
{
netif_set_status_callback(&if_handle->netif,
wm_netif_status_static_callback);
}
break;
case ADDR_TYPE_DHCP:
/* Reset the address since we might be transitioning from static to DHCP */
memset(&if_handle->ipaddr, 0, sizeof(ip_addr_t));
memset(&if_handle->nmask, 0, sizeof(ip_addr_t));
memset(&if_handle->gw, 0, sizeof(ip_addr_t));
netifapi_netif_set_addr(&if_handle->netif, &if_handle->ipaddr,
&if_handle->nmask, &if_handle->gw);
netif_set_status_callback(&if_handle->netif,
wm_netif_status_callback);
netifapi_netif_set_up(&if_handle->netif);
netifapi_dhcp_start(&if_handle->netif);
break;
default:
break;
}
/* Finally this should send the following event. */
if (if_handle == &g_mlan) {
// static IP up;
/* XXX For DHCP, the above event will only indicate that the
* DHCP address obtaining process has started. Once the DHCP
* address has been obtained, another event,
* WD_EVENT_NET_DHCP_CONFIG, should be sent to the wlcmgr.
*/
up_iface = 1;
// we always set sta netif as the default.
sta_set_default_netif();
} else {
// softap IP up, start dhcp server;
dhcp_server_start(net_get_uap_handle());
up_iface = 0;
// as the default netif is sta's netif, so ap need to send
// boardcast or not sub net packets, need set ap netif before
// send those packets, after finish sending, reset default netif
// to sta's netif.
os_printf("def netif is no ap's netif, sending boardcast or no-subnet ip packets may failed\r\n");
}
return 0;
}
int net_get_if_addr(struct wlan_ip_config *addr, void *intrfc_handle)
{
const ip_addr_t *tmp;
struct interface *if_handle = (struct interface *)intrfc_handle;
if(netif_is_up(&if_handle->netif)) {
addr->ipv4.address = if_handle->netif.ip_addr.addr;
addr->ipv4.netmask = if_handle->netif.netmask.addr;
addr->ipv4.gw = if_handle->netif.gw.addr;
tmp = dns_getserver(0);
addr->ipv4.dns1 = tmp->addr;
tmp = dns_getserver(1);
addr->ipv4.dns2 = tmp->addr;
}
return 0;
}
int net_get_if_macaddr(void *macaddr, void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
os_memcpy(macaddr, &if_handle->netif.hwaddr[0], if_handle->netif.hwaddr_len);
return 0;
}
#ifdef CONFIG_IPV6
int net_get_if_ipv6_addr(struct wlan_ip_config *addr, void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
int i;
for (i = 0; i < MAX_IPV6_ADDRESSES; i++) {
memcpy(addr->ipv6[i].address,
if_handle->netif.ip6_addr[i].addr, 16);
addr->ipv6[i].addr_state = if_handle->netif.ip6_addr_state[i];
}
/* TODO carry out more processing based on IPv6 fields in netif */
return 0;
}
int net_get_if_ipv6_pref_addr(struct wlan_ip_config *addr, void *intrfc_handle)
{
int i, ret = 0;
struct interface *if_handle = (struct interface *)intrfc_handle;
for (i = 0; i < MAX_IPV6_ADDRESSES; i++) {
if (if_handle->netif.ip6_addr_state[i] == IP6_ADDR_PREFERRED) {
memcpy(addr->ipv6[ret++].address,
if_handle->netif.ip6_addr[i].addr, 16);
}
}
return ret;
}
#endif /* CONFIG_IPV6 */
int net_get_if_ip_addr(uint32_t *ip, void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
*ip = if_handle->netif.ip_addr.addr;
return 0;
}
int net_get_if_gw_addr(uint32_t *ip, void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
*ip = if_handle->netif.gw.addr;
return 0;
}
int net_get_if_ip_mask(uint32_t *nm, void *intrfc_handle)
{
struct interface *if_handle = (struct interface *)intrfc_handle;
*nm = if_handle->netif.netmask.addr;
return 0;
}
void net_configure_dns(struct wlan_ip_config *ip)
{
ip_addr_t tmp;
if (ip->ipv4.addr_type == ADDR_TYPE_STATIC) {
if (ip->ipv4.dns1 == 0)
ip->ipv4.dns1 = ip->ipv4.gw;
if (ip->ipv4.dns2 == 0)
ip->ipv4.dns2 = ip->ipv4.dns1;
tmp.addr = ip->ipv4.dns1;
dns_setserver(0, &tmp);
tmp.addr = ip->ipv4.dns2;
dns_setserver(1, &tmp);
}
/* DNS MAX Retries should be configured in lwip/dns.c to 3/4 */
/* DNS Cache size of about 4 is sufficient */
}
void net_wlan_initial(void)
{
net_ipv4stack_init();
#ifdef CONFIG_IPV6
net_ipv6stack_init(&g_mlan.netif);
#endif /* CONFIG_IPV6 */
}
void net_wlan_add_netif(void *mac)
{
VIF_INF_PTR vif_entry = NULL;
struct interface *wlan_if = NULL;
err_t err;
u8 vif_idx;
u8 *b = (u8*)mac;
if(!b || (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])))
return;
vif_idx = rwm_mgmt_vif_mac2idx(mac);
if(vif_idx == 0xff) {
os_printf("net_add_netif-not-found\r\n");
return ;
}
vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx);
if(!vif_entry) {
os_printf("net_wlan_add_netif not vif found, %d\r\n", vif_idx);
return ;
}
if(vif_entry->type == VIF_AP) {
wlan_if = &g_uap;
} else if(vif_entry->type == VIF_STA) {
wlan_if = &g_mlan;
} else {
os_printf("net_wlan_add_netif with other role\r\n");
return ;
}
wlan_if->ipaddr.addr = INADDR_ANY;
err = netifapi_netif_add(&wlan_if->netif,
&wlan_if->ipaddr,
&wlan_if->ipaddr,
&wlan_if->ipaddr,
(void*)vif_entry,
ethernetif_init,
tcpip_input);
if (err)
{
os_printf("net_wlan_add_netif failed\r\n");
}
else
{
vif_entry->priv = &wlan_if->netif;
}
os_printf("[net]addvif_idx:%d\r\n", vif_idx);
}
void net_wlan_remove_netif(void *mac)
{
err_t err;
u8 vif_idx;
VIF_INF_PTR vif_entry = NULL;
struct netif *netif = NULL;
u8 *b = (u8*)mac;
if(!b || (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])))
return;
vif_idx = rwm_mgmt_vif_mac2idx(mac);
if(vif_idx == 0xff) {
os_printf("net_wlan_add_netif not vif idx found\r\n");
return ;
}
vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx);
if(!vif_entry) {
os_printf("net_wlan_add_netif not vif found, %d\r\n", vif_idx);
return ;
}
netif = (struct netif *)vif_entry->priv;
if(!netif) {
os_printf("net_wlan_remove_netif netif is null\r\n");
return;
}
err = netifapi_netif_remove(netif);
if(err != ERR_OK) {
os_printf("net_wlan_remove_netif failed\r\n");
} else {
netif->state = NULL;
}
os_printf("[net]remoVif_idx:%d\r\n", vif_idx);
}
//eof

View File

@@ -1,21 +0,0 @@
#ifndef _NET_H_
#define _NET_H_
#include "lwip_netif_address.h"
extern void uap_ip_down(void);
extern void uap_ip_start(void);
extern void sta_ip_down(void);
extern void sta_ip_start(void);
extern uint32_t uap_ip_is_start(void);
extern uint32_t sta_ip_is_start(void);
extern void *net_get_sta_handle(void);
extern void *net_get_uap_handle(void);
extern void net_wlan_remove_netif(void *mac);
extern int net_get_if_macaddr(void *macaddr, void *intrfc_handle);
extern int net_get_if_addr(struct wlan_ip_config *addr, void *intrfc_handle);
extern void ip_address_set(int iface, int dhcp, char *ip, char *mask, char*gw, char*dns);
#endif // _NET_H_
// eof

View File

@@ -1,500 +0,0 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/* lwIP includes. */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#include "sys_rtos.h"
#include "lwip/timeouts.h"
#include "rtos_pub.h"
#include "portmacro.h"
#define CFG_ENABLE_LWIP_MUTEX 1
#if CFG_ENABLE_LWIP_MUTEX
static sys_mutex_t sys_arch_mutex;
#endif
/*-----------------------------------------------------------------------------------*/
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
(void ) size;
if (size > 0)
*mbox = xQueueCreate( size, sizeof( void * ) );
else
*mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
#if SYS_STATS
++lwip_stats.sys.mbox.used;
if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
}
#endif /* SYS_STATS */
if (*mbox == NULL)
return ERR_MEM;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
programming error in lwIP and the developer should be notified.
*/
void sys_mbox_free(sys_mbox_t *mbox)
{
if( uxQueueMessagesWaiting( *mbox ) )
{
/* Line for breakpoint. Should never break here! */
portNOP();
#if SYS_STATS
lwip_stats.sys.mbox.err++;
#endif /* SYS_STATS */
// TODO notify the user of failure.
}
vQueueDelete( *mbox );
#if SYS_STATS
--lwip_stats.sys.mbox.used;
#endif /* SYS_STATS */
}
/*-----------------------------------------------------------------------------------*/
// Posts the "msg" to the mailbox.
void sys_mbox_post(sys_mbox_t *mbox, void *data)
{
while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){}
}
/*-----------------------------------------------------------------------------------*/
// Try to post the "msg" to the mailbox.
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
err_t result;
if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS )
{
result = ERR_OK;
}
else {
// could not post, queue must be full
result = ERR_MEM;
#if SYS_STATS
lwip_stats.sys.mbox.err++;
#endif /* SYS_STATS */
}
return result;
}
/*-----------------------------------------------------------------------------------*/
/*
Blocks the thread until a message arrives in the mailbox, but does
not block the thread longer than "timeout" milliseconds (similar to
the sys_arch_sem_wait() function). The "msg" argument is a result
parameter that is set by the function (i.e., by doing "*msg =
ptr"). The "msg" parameter maybe NULL to indicate that the message
should be dropped.
The return values are the same as for the sys_arch_sem_wait() function:
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
timeout.
Note that a function with a similar name, sys_mbox_fetch(), is
implemented by lwIP.
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
void *dummyptr;
portTickType StartTime, EndTime, Elapsed;
StartTime = xTaskGetTickCount();
if ( msg == NULL )
{
msg = &dummyptr;
}
if ( timeout != 0 )
{
if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) )
{
EndTime = xTaskGetTickCount();
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
return ( Elapsed );
}
else // timed out blocking for message
{
*msg = NULL;
return SYS_ARCH_TIMEOUT;
}
}
else // block forever for a message.
{
while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary
EndTime = xTaskGetTickCount();
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
return ( Elapsed ); // return time blocked TODO test
}
}
/*-----------------------------------------------------------------------------------*/
/*
Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll
return with SYS_MBOX_EMPTY. On success, 0 is returned.
*/
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{
void *dummyptr;
if ( msg == NULL )
{
msg = &dummyptr;
}
if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) )
{
return ERR_OK;
}
else
{
return SYS_MBOX_EMPTY;
}
}
/*----------------------------------------------------------------------------------*/
int sys_mbox_valid(sys_mbox_t *mbox)
{
if (*mbox == SYS_MBOX_NULL)
return 0;
else
return 1;
}
/*-----------------------------------------------------------------------------------*/
void sys_mbox_set_invalid(sys_mbox_t *mbox)
{
*mbox = SYS_MBOX_NULL;
}
/*-----------------------------------------------------------------------------------*/
// Creates a new semaphore. The "count" argument specifies
// the initial state of the semaphore.
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
vSemaphoreCreateBinary(*sem );
if(*sem == NULL)
{
#if SYS_STATS
++lwip_stats.sys.sem.err;
#endif /* SYS_STATS */
return ERR_MEM;
}
if(count == 0) // Means it can't be taken
{
xSemaphoreTake(*sem,1);
}
#if SYS_STATS
++lwip_stats.sys.sem.used;
if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
#endif /* SYS_STATS */
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
Blocks the thread while waiting for the semaphore to be
signaled. If the "timeout" argument is non-zero, the thread should
only be blocked for the specified time (measured in
milliseconds).
If the timeout argument is non-zero, the return value is the number of
milliseconds spent waiting for the semaphore to be signaled. If the
semaphore wasn't signaled within the specified time, the return value is
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
(i.e., it was already signaled), the function may return zero.
Notice that lwIP implements a function with a similar name,
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
*/
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
portTickType StartTime, EndTime, Elapsed;
StartTime = xTaskGetTickCount();
if( timeout != 0)
{
if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE )
{
EndTime = xTaskGetTickCount();
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
return (Elapsed); // return time blocked TODO test
}
else
{
return SYS_ARCH_TIMEOUT;
}
}
else // must block without a timeout
{
while( xSemaphoreTake( *sem, portMAX_DELAY) != pdTRUE)
{
;
}
EndTime = xTaskGetTickCount();
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
return ( Elapsed ); // return time blocked
}
}
/*-----------------------------------------------------------------------------------*/
// Signals a semaphore
void sys_sem_signal(sys_sem_t *sem)
{
xSemaphoreGive(*sem);
}
/*-----------------------------------------------------------------------------------*/
// Deallocates a semaphore
void sys_sem_free(sys_sem_t *sem)
{
#if SYS_STATS
--lwip_stats.sys.sem.used;
#endif /* SYS_STATS */
vQueueDelete(*sem);
}
/*-----------------------------------------------------------------------------------*/
int sys_sem_valid(sys_sem_t *sem)
{
if (*sem == SYS_SEM_NULL)
return 0;
else
return 1;
}
/*-----------------------------------------------------------------------------------*/
void sys_sem_set_invalid(sys_sem_t *sem)
{
*sem = SYS_SEM_NULL;
}
/*-----------------------------------------------------------------------------------*/
err_t sys_mutex_trylock(sys_mutex_t *pxMutex)
{
if (xSemaphoreTake(*pxMutex, 0) == pdPASS)
return 0;
else
return -1;
}
/*-----------------------------------------------------------------------------------*/
// Initialize sys arch
void sys_init(void)
{
#if CFG_ENABLE_LWIP_MUTEX
sys_mutex_new(&sys_arch_mutex);
#endif
}
/*-----------------------------------------------------------------------------------*/
/* Mutexes*/
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Create a new mutex*/
err_t sys_mutex_new(sys_mutex_t *mutex) {
*mutex = xSemaphoreCreateMutex();
if(*mutex == NULL)
{
#if SYS_STATS
++lwip_stats.sys.mutex.err;
#endif /* SYS_STATS */
return ERR_MEM;
}
#if SYS_STATS
++lwip_stats.sys.mutex.used;
if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) {
lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used;
}
#endif /* SYS_STATS */
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* Deallocate a mutex*/
void sys_mutex_free(sys_mutex_t *mutex)
{
#if SYS_STATS
--lwip_stats.sys.mutex.used;
#endif /* SYS_STATS */
vQueueDelete(*mutex);
}
/*-----------------------------------------------------------------------------------*/
/* Lock a mutex*/
void sys_mutex_lock(sys_mutex_t *mutex)
{
sys_arch_sem_wait(mutex, BEKEN_WAIT_FOREVER);
}
/*-----------------------------------------------------------------------------------*/
/* Unlock a mutex*/
void sys_mutex_unlock(sys_mutex_t *mutex)
{
xSemaphoreGive(*mutex);
}
/*-----------------------------------------------------------------------------------*/
// TODO
/*-----------------------------------------------------------------------------------*/
/*
Starts a new thread with priority "prio" that will begin its execution in the
function "thread()". The "arg" argument will be passed as an argument to the
thread() function. The id of the new thread is returned. Both the id and
the priority are system dependent.
*/
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
{
xTaskHandle CreatedTask;
int result;
result = xTaskCreate( thread, ( portCHAR * ) name, stacksize, arg, prio, &CreatedTask );
if(result == pdPASS)
{
return CreatedTask;
}
else
{
return NULL;
}
}
int sys_thread_delete(xTaskHandle pid)
{
return pdPASS;
}
/*
This optional function does a "fast" critical region protection and returns
the previous protection level. This function is only called during very short
critical regions. An embedded system which supports ISR-based drivers might
want to implement this function by disabling interrupts. Task-based systems
might want to implement this by using a mutex or disabling tasking. This
function should support recursive calls from the same task or interrupt. In
other words, sys_arch_protect() could be called while already protected. In
that case the return value indicates that it is already protected.
sys_arch_protect() is only required if your port is supporting an operating
system.
*/
sys_prot_t sys_arch_protect(void)
{
#if CFG_ENABLE_LWIP_MUTEX
sys_mutex_lock(&sys_arch_mutex);
return 0;
#else
return port_disable_interrupts_flag();
#endif
}
/*
This optional function does a "fast" set of critical region protection to the
value specified by pval. See the documentation for sys_arch_protect() for
more information. This function is only required if your port is supporting
an operating system.
*/
void sys_arch_unprotect(sys_prot_t pval)
{
#if CFG_ENABLE_LWIP_MUTEX
(void)pval;
sys_mutex_unlock(&sys_arch_mutex);
#else
port_enable_interrupts_flag(pval);
#endif
}
/*
* Prints an assertion messages and aborts execution.
*/
void sys_assert( const char *msg )
{
(void) msg;
/*FSL:only needed for debugging*/
os_printf(msg);
os_printf("\n\r");
vPortEnterCritical();
for(;;)
;
}
u32_t sys_now(void)
{
return xTaskGetTickCount() * portTICK_RATE_MS;
}
u32_t sys_jiffies(void)
{
return xTaskGetTickCount() * portTICK_RATE_MS;
}
void sys_arch_msleep(int ms)
{
vTaskDelay(ms / portTICK_RATE_MS);
}
// eof

94
proj/minimal/Makefile Normal file
View File

@@ -0,0 +1,94 @@
# Copyright (c) 2001, Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# $Id: Makefile,v 1.1.1.1 2002/10/19 12:59:33 likewise Exp $
CCDEP=gcc
CC=gcc
CFLAGS=-g -Wall -DIPv4 -Os -fpack-struct
LWIPARCH=unix
ARFLAGS=rs
LWIPDIR=../../src
CFLAGS:=$(CFLAGS) \
-I$(LWIPDIR)/include -I$(LWIPDIR)/arch/$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-Iapps -I.
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/stats.c $(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_input.c \
$(LWIPDIR)/core/tcp_output.c $(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c $(LWIPDIR)/core/ipv4/ip.c \
$(LWIPDIR)/core/inet.c $(LWIPDIR)/core/ipv4/ip_addr.c
# NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/etharp.c mintapif.c
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(NETIFFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
# APPFILES
APPFILES=echo.c
LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)
all ipv4 compile: minimal
.PHONY: all
clean:
rm -f *.o $(LWIPLIB) $(APPLIB) minimal .depend* *.core core
depend dep: .depend
include .depend
$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?
$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?
.depend: main.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
minimal: .depend $(LWIPLIB) $(APPLIB) main.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -o minimal main.o $(APPLIB) $(LWIPLIB)

3
proj/minimal/README Normal file
View File

@@ -0,0 +1,3 @@
This is an example of a very minimal lwIP project. It runs in a single
thread and runs a single example application - an echo server. The
echo application is implemented using the raw API.

220
proj/minimal/echo.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
struct echo_state {
struct pbuf *p;
u8_t failed;
#define FAILED_MAX 8
};
/*-----------------------------------------------------------------------------------*/
static void
echo_err(void *arg, err_t err)
{
struct echo_state *es = arg;
if(arg != NULL) {
pbuf_free(es->p);
mem_free(arg);
}
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct echo_state *es)
{
tcp_arg(pcb, NULL);
#if 0
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
#endif /* 0 */
if(es != NULL) {
pbuf_free(es->p);
mem_free(es);
}
tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_buf(struct tcp_pcb *pcb, struct echo_state *es)
{
struct pbuf *q;
do {
q = es->p;
es->p = pbuf_dechain(q);
if(tcp_write(pcb, q->payload, q->len, 1) == ERR_MEM) {
pbuf_chain(q, es->p);
es->p = q;
return;
}
tcp_recved(pcb, q->len);
pbuf_free(q);
} while(es->p != NULL);
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_poll(void *arg, struct tcp_pcb *pcb)
{
struct echo_state *es;
if(arg == NULL) {
return tcp_close(pcb);
}
es = arg;
if(es->failed >= FAILED_MAX) {
close_conn(pcb, es);
tcp_abort(pcb);
return ERR_ABRT;
}
if(es->p != NULL) {
++es->failed;
send_buf(pcb, es);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct echo_state *es;
es = arg;
if(es != NULL && es->p != NULL) {
send_buf(pcb, es);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct echo_state *es;
es = arg;
if(p == NULL) {
close_conn(pcb, es);
return ERR_OK;
}
if(es->p != NULL) {
pbuf_chain(es->p, p);
} else {
es->p = p;
}
send_buf(pcb, es);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct echo_state *es;
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
es = mem_malloc(sizeof(struct echo_state));
if(es == NULL) {
return ERR_MEM;
}
/* Initialize the structure. */
es->p = NULL;
es->failed = 0;
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, es);
/* Tell TCP that we wish to be informed of incoming data by a call
to the http_recv() function. */
#if 0
tcp_recv(pcb, echo_recv);
tcp_err(pcb, echo_err);
#endif /* 0 */
tcp_poll(pcb, echo_poll, 2);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
echo_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 7);
pcb = tcp_listen(pcb);
#if 0
tcp_accept(pcb, echo_accept);
#endif /* 0 */
}
/*-----------------------------------------------------------------------------------*/
err_t
lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
enum lwip_event ev, struct pbuf *p,
u16_t size, err_t err)
{
switch(ev) {
case LWIP_EVENT_ACCEPT:
return echo_accept(arg, pcb, err);
case LWIP_EVENT_SENT:
return echo_sent(arg, pcb, size);
case LWIP_EVENT_RECV:
return echo_recv(arg, pcb, p, err);
case LWIP_EVENT_ERR:
echo_err(arg, err);
break;
case LWIP_EVENT_POLL:
return echo_poll(arg, pcb);
default:
break;
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/

168
proj/minimal/lwipopts.h Normal file
View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
#define NO_SYS 1
#define LWIP_EVENT_API 1
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 2
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 1000
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 8
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 2
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 8
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 0
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 0
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs. */
#define MEMP_NUM_API_MSG 0
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG 0
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 0
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 8
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
#define PBUF_LINK_HLEN 16
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0
/* TCP Maximum segment size. */
#define TCP_MSS 128
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 256
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS
/* TCP receive window. */
#define TCP_WND 512
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 0
/* If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 0
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK 1
/* ---------- UDP options ---------- */
#define LWIP_UDP 0
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
/*#define STATS*/
#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */
#endif /* __LWIPOPTS_H__ */

101
proj/minimal/main.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "mintapif.h"
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
struct ip_addr ipaddr, netmask, gw;
struct netif *netif;
#ifdef PERF
perf_init("/tmp/minimal.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
mem_init();
memp_init();
pbuf_init();
netif_init();
ip_init();
udp_init();
tcp_init();
printf("TCP/IP initialized.\n");
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif = netif_add(&ipaddr, &netmask, &gw, mintapif_init, ip_input);
netif_set_default(netif);
echo_init();
printf("Applications started.\n");
while(1) {
if(mintapif_wait(netif, 100) == MINTAPIF_TIMEOUT) {
tcp_tmr();
}
}
return 0;
}
/*-----------------------------------------------------------------------------------*/

354
proj/minimal/mintapif.c Normal file
View File

@@ -0,0 +1,354 @@
/*-----------------------------------------------------------------------------------*/
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
#ifdef linux
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#define DEVTAP "/dev/net/tun"
#else /* linux */
#define DEVTAP "/dev/tap0"
#endif /* linux */
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "netif/etharp.h"
#include "mintapif.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 't'
struct mintapif {
struct eth_addr *ethaddr;
/* Add whatever per-interface state that is needed here. */
u32_t lasttime;
int fd;
};
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
/* Forward declarations. */
static void mintapif_input(struct netif *netif);
static err_t mintapif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
/*-----------------------------------------------------------------------------------*/
static void
low_level_init(struct netif *netif)
{
struct mintapif *mintapif;
char buf[1024];
mintapif = netif->state;
/* Obtain MAC address from network interface. */
mintapif->ethaddr->addr[0] = 1;
mintapif->ethaddr->addr[1] = 2;
mintapif->ethaddr->addr[2] = 3;
mintapif->ethaddr->addr[3] = 4;
mintapif->ethaddr->addr[4] = 5;
mintapif->ethaddr->addr[5] = 6;
/* Do whatever else is needed to initialize interface. */
mintapif->fd = open(DEVTAP, O_RDWR);
if(mintapif->fd == -1) {
perror("tapif: tapif_init: open");
exit(1);
}
#ifdef linux
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
if (ioctl(mintapif->fd, TUNSETIFF, (void *) &ifr) < 0) {
perror(buf);
exit(1);
}
}
#endif /* Linux */
snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d",
ip4_addr1(&(netif->gw)),
ip4_addr2(&(netif->gw)),
ip4_addr3(&(netif->gw)),
ip4_addr4(&(netif->gw)));
system(buf);
mintapif->lasttime = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_output():
*
* Should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct mintapif *mintapif;
struct pbuf *q;
char buf[1500];
char *bufptr;
mintapif = netif->state;
/* initiate transfer(); */
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
variable. */
/* send data from(q->payload, q->len); */
bcopy(q->payload, bufptr, q->len);
bufptr += q->len;
}
/* signal that packet should be sent(); */
if(write(mintapif->fd, buf, p->tot_len) == -1) {
perror("tapif: write");
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_input():
*
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
*/
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct mintapif *mintapif)
{
struct pbuf *p, *q;
u16_t len;
char buf[1500];
char *bufptr;
/* Obtain the size of the packet and put it into the "len"
variable. */
len = read(mintapif->fd, buf, sizeof(buf));
/* if(((double)rand()/(double)RAND_MAX) < 0.1) {
printf("drop\n");
return NULL;
}*/
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
if(p != NULL) {
/* We iterate over the pbuf chain until we have read the entire
packet into the pbuf. */
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
variable. */
/* read data into(q->payload, q->len); */
bcopy(bufptr, q->payload, q->len);
bufptr += q->len;
}
/* acknowledge that packet has been read(); */
} else {
/* drop packet(); */
printf("Could not allocate pbufs\n");
}
return p;
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actuall transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
mintapif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
p = etharp_output(netif, ipaddr, p);
if(p != NULL) {
return low_level_output(netif, p);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
mintapif_input(struct netif *netif)
{
struct mintapif *mintapif;
struct eth_hdr *ethhdr;
struct pbuf *p, *q;
mintapif = netif->state;
p = low_level_input(mintapif);
if(p != NULL) {
#ifdef LINK_STATS
stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
q = NULL;
switch(htons(ethhdr->type)) {
case ETHTYPE_IP:
q = etharp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
q = etharp_arp_input(netif, mintapif->ethaddr, p);
break;
default:
pbuf_free(p);
break;
}
if(q != NULL) {
low_level_output(netif, q);
pbuf_free(q);
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
void
mintapif_init(struct netif *netif)
{
struct mintapif *mintapif;
mintapif = mem_malloc(sizeof(struct mintapif));
netif->state = mintapif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = mintapif_output;
netif->linkoutput = low_level_output;
mintapif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
}
/*-----------------------------------------------------------------------------------*/
enum mintapif_signal
mintapif_wait(struct netif *netif, u16_t time)
{
fd_set fdset;
struct timeval tv, now;
struct timezone tz;
int ret;
struct mintapif *mintapif;
mintapif = netif->state;
while(1) {
if(mintapif->lasttime >= (u32_t)time * 1000) {
mintapif->lasttime = 0;
return MINTAPIF_TIMEOUT;
}
tv.tv_sec = 0;
tv.tv_usec = (u32_t)time * 1000 - mintapif->lasttime;
FD_ZERO(&fdset);
FD_SET(mintapif->fd, &fdset);
gettimeofday(&now, &tz);
ret = select(mintapif->fd + 1, &fdset, NULL, NULL, &tv);
if(ret == 0) {
mintapif->lasttime = 0;
return MINTAPIF_TIMEOUT;
}
gettimeofday(&tv, &tz);
mintapif->lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec);
mintapif_input(netif);
}
return MINTAPIF_PACKET;
}

View File

@@ -1,10 +1,8 @@
/**
* @file
* NETBIOS name service responder
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,39 +11,35 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_APPS_NETBIOS_H
#define LWIP_HDR_APPS_NETBIOS_H
#ifndef __MINTAPIF_H__
#define __MINTAPIF_H__
#include "lwip/apps/netbiosns_opts.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
enum mintapif_signal {
MINTAPIF_TIMEOUT,
MINTAPIF_PACKET
};
void netbiosns_init(void);
#ifndef NETBIOS_LWIP_NAME
void netbiosns_set_name(const char* hostname);
#endif
void netbiosns_stop(void);
void mintapif_init(struct netif *netif);
enum mintapif_signal mintapif_wait(struct netif *netif, u16_t time);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_NETBIOS_H */
#endif /* __MINTAPIF_H__ */

111
proj/unixsim/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# Copyright (c) 2001, Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# $Id: Makefile,v 1.1.1.1 2002/10/19 12:59:37 likewise Exp $
CCDEP=gcc
CC=gcc
CFLAGS=-g -Wall -DIPv4 -DLWIP_DEBUG -pedantic
LDFLAGS=-lpcap
LWIPARCH=unix
ARFLAGS=rs
LWIPDIR=../../src
CFLAGS:=$(CFLAGS) \
-I$(LWIPDIR)/include -I$(LWIPDIR)/arch/$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-Iapps -I.
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/stats.c $(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_input.c \
$(LWIPDIR)/core/tcp_output.c $(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c $(LWIPDIR)/core/ipv4/ip.c \
$(LWIPDIR)/core/inet.c $(LWIPDIR)/core/ipv4/ip_addr.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \
$(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c
# NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/loopif.c \
$(LWIPDIR)/netif/tcpdump.c $(LWIPDIR)/netif/etharp.c
# ARCHFILES: Archiecture specific files.
ARCHFILES=$(wildcard $(LWIPDIR)/arch/$(LWIPARCH)/*.c $(LWIPDIR)/arch/$(LWIPARCH)/netif/*.c)
# APPFILES: Applications.
APPFILES=apps/fs.c apps/httpd.c \
apps/udpecho.c apps/tcpecho.c \
apps/shell.c
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)
all ipv4 compile: simhost simnode simrouter
.PHONY: all
clean:
rm -f *.o $(LWIPLIB) $(APPLIB) simhost simnode simrouter *.s .depend* *.core core
depend dep: .depend
include .depend
$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?
$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?
.depend: simhost.c simnode.c simrouter.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
simhost: .depend $(LWIPLIB) $(APPLIB) simhost.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simhost simhost.o $(APPLIB) $(LWIPLIB)
simrouter: .depend $(LWIPLIB) $(APPLIB) simrouter.o
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simrouter simrouter.o $(APPLIB) $(LWIPLIB)
simnode: .depend $(LWIPLIB) $(APPLIB) simnode.o
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simnode simnode.o $(APPLIB) $(LWIPLIB)

47
proj/unixsim/README Normal file
View File

@@ -0,0 +1,47 @@
This directory contains an example of how a project using lwIP might
look. It is also the development platform of lwIP, since it can be run
as a user process under FreeBSD or Linux. There are also a number of
example applications (including a simple web server) in the apps/
directory.
Some short instructions on how to build and run lwIP on a FreeBSD or
Linux host. For FreeBSD, the tap interface must be enabled in the
kernel configuration and the kernel must be recompiled. The tap
interface is enabled by adding the line "pseudo-device tap" in the
kernel configuration. See Chapter 9 in the FreeBSD handbook for
instructions on how to build a custom FreeBSD kernel.
* Compile the code. This must be done by using GNU Make. Under
FreeBSD, GNU Make can be found in the ports collection under
/usr/ports/devel/gmake (type "make install distclean" to
install). Under Linux, GNU Make is the default "make".
> gmake (FreeBSD)
> make (Linux)
* The compilation process produces the executable file "simhost". To
run this, you have to be root.
> su (Type password for the root account)
# ./simhost
* The lwIP TCP/IP stack is now running with IP address
192.168.0.2. Some things that you can try:
To see the packets that are going to and from the lwIP stack, run
tcpdump:
# tcpdump -l -n -i tap0
You can ping lwIP:
> ping 192.168.0.2
For a telnet shell, run:
> telnet 192.168.0.2
Finally, "simhost" also includes a simple web server; the URL is
of course http://192.168.0.2/.

55
proj/unixsim/apps/fs.c Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/def.h"
#include "fs.h"
#include "fsdata.h"
#include "fsdata.c"
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
int
fs_open(char *name, struct fs_file *file)
{
struct fsdata_file_noconst *f;
for(f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next) {
if(!strcmp(name, f->name)) {
file->data = f->data;
file->len = f->len;
return 1;
}
}
return 0;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,8 +1,8 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -11,31 +11,34 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_FSDATA_H
#define LWIP_FSDATA_H
#ifndef __FS_H__
#define __FS_H__
#include "lwip/apps/httpd_opts.h"
#include "lwip/apps/fs.h"
struct fs_file {
char *data;
int len;
};
/* THIS FILE IS DEPRECATED AND WILL BE REMOVED IN THE FUTURE */
/* content was moved to fs.h to simplify #include structure */
/* file must be allocated by caller and will be filled in
by the function. */
int fs_open(char *name, struct fs_file *file);
#endif /* LWIP_FSDATA_H */
#endif /* __FS_H__ */

View File

@@ -0,0 +1,191 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Documentation</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
[Documentation]
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Documentation</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<ul>
<li><a href="os.html">Using lwIP with and without an operating
system</a>.
<br><br>
<li>The lwIP source archive contains documentation on how to port lwIP
and how to write applications using the native API. They can also be
found here: <a href="doc/sys_arch.txt">sys_arch.txt</a>, <a
href="doc/rawapi.txt">rawapi.txt</a>.
<br><br>
<li>Selected messages from the mailinglist: <a
href="maillist/msg00231.html">lwIP memory buffers and allocators</a>,
<a href="maillist/msg00227.html">Threads, semaphores and raw interface
question</a>, <a href="maillist/msg00242.html">Threads, semaphores and
raw interface question [2]</a>. <a href="maillist/msg00460.html">Some notes on using lwIP with the development enviroment ADS
1.1 from ARM.</a>
<br><br>
<li>A report describing the design and implementation of an old
version of lwIP. The algorithms and data structures used both in the
protocol implementations and in the sub systems such as the memory and
buffer management systems are described. Also included in this report
is a reference manual for the lwIP sequential API and some code
examples of using lwIP. <a href="doc/lwip.pdf">PDF</a>, <a
href="doc/lwip.ps.gz">.ps.gz</a>.
<br><br>
<li>Slides from a presentation that talks a bit about lwIP: <a
href="doc/pres.pdf">PDF</a> (86k), <a href="doc/pres.ps.gz">.ps.gz</a>
(36k).
</ul>
<p align="justify">
For more documentation regarding lwIP and a proxy architecture to
support TCP/IP communication for small clients, look in <a
href="/~adam/publications.html">Adam Dunkels' masters thesis</a>.
</p>
<p align="justify">
The <a href="mailinglist.html">lwIP mailing list</a> can be used to
discuss lwIP.
</p>
<p align="justify">
For questions or suggestions, please contact the author at <a
href="mailto:Adam Dunkels <adam@sics.se>">Adam Dunkels
&lt;adam@sics.se&gt;</a>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:01 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
[Documentation]
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,232 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Download</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
[Download]
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Download</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<p align="justify">
lwIP is avaliable for download provided that you read and accept <a
href="licence.html">this</a> BSD-style license.
</p>
<h3>Release versions</h3>
<p align="justify">
The latest version is 0.5.3. (Older versions are also provided for an
unknown reason.)
</p>
<ul>
<li>Version 0.5.3 (latest): <a
href="download/?f=lwip-0.5.3.tar.gz">lwip-0.5.3.tar.gz</a>
<br><br>
<li>
<font size="-2">
Obsolete versions: <a
href="download/?f=lwip-0.5.2.tar.gz">lwip-0.5.2.tar.gz</a>
<a
href="download/?f=lwip-0.5.1.tar.gz">lwip-0.5.1.tar.gz</a>
<a
href="download/?f=lwip-0.5.0.tar.gz">lwip-0.5.0.tar.gz</a>
<a
href="download/?f=lwip-0.4.2.tar.gz">lwip-0.4.2.tar.gz</a>
<a
href="download/?f=lwip-0.4.1.tar.gz">lwip-0.4.1.tar.gz</a>
<a
href="download/?f=lwip-0.4.tar.gz">lwip-0.4.tar.gz</a>
<a
href="download/?f=lwip-0.3.1.tar.gz">lwip-0.3.1.tar.gz</a>
<a
href="download/?f=lwip-0.3.tar.gz">lwip-0.3.tar.gz</a>
<a
href="download/?f=lwip-0.2.tar.gz">lwip-0.2.tar.gz</a>
</font>
<br>
</ul>
<h3>Development version</h3>
<p align="justify">
The latest development code from the CVS is also avaliable <a
href="download/?f=lwip-cvs.tar.gz">here</a>. Note that this code may
very well be unstable and might not even compile.
</p>
<h3>Source code online</h3>
<p align="justify">
Joe MacDonald has put an HTML version of the latest lwIP source code
online at <a
href="http://www.deserted.net/lwIP/">http://www.deserted.net/lwIP/</a>.
</p>
<h3>Ports</h3>
<p align="justify">
Florian Shulze has ported lwIP to DJGPP/MS-DOS and to Visual C++
6.0/Win32. They can be downloaded <a
href="http://homepages.fh-giessen.de/~hg10836/dev/djgpp/lwipdjgpptest-0.1.zip">here</a>
(DJGPP/MS-DOS) and <a
href="http://homepages.fh-giessen.de/~hg10836/crowproductions/dev/lwip-win32-msvc-0.1.zip">here</a>
(Visual C++ 6.0/Win32).
</p>
<h3>Add-ons/drivers/applications</h3>
<h4>DHCP client</h4>
<p align="justify">
Leon Woestenberg from Axon Digital Design B.V. has written a CS8900a
network interface driver and is currently developing a DHCP client for
lwIP. They can both be found <a
href="http://www.esrac.ele.tue.nl/~leon/lwip/">here</a>. The plan is
to eventually integrate Leon's DHCP client in the main lwIP
distribution.
</p>
<h4>IGMPv2 implementation</h4>
<p align="justify">
Steve Reynolds of Citel Technologies Ltd. has donated his IGMPv2
implementation for lwIP to the community. It is avaliable for download
<a href="download/igmpfiles.zip">here</a> (note that the copyright and
license differs slightly from lwIP - read the license in the igmp.c
file). The plan is to integrate his code into the main lwIP
distribution.
</p>
<h4>Alternative BSD socket layer</h4>
<p align="justify">
Paul Sheer has incorporated lwIP into his PaulOS system and has
written an alternative BSD socket layer. It is avaliable for download
<a href="download/bsdsocket.c">here</a>. It is copyright Paul Sheer
and licensed under the <a
href="http://www.gnu.org/licenses/gpl.html">GNU GPL</a>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:06 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
[Download]
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 724 B

View File

@@ -0,0 +1,169 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - lwIP source code licence</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>lwIP source code licence</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
Copyright (c) 2001, Swedish Institute of Computer Science.
All rights reserved.<br>
<br>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:<br>
<ol>
<li> Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.<br>
<br>
<li> Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.<br>
<br>
<li> Neither the name of the Institute nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission. <br>
</ol>
<br>
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS `AS IS' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. <br>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:01 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,266 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Links</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
[Links]
<hr>
</td></tr>
<tr>
<td><center><h2>Links</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
lwIP pages:
<ul>
<li><a href="http://www.esrac.ele.tue.nl/~leon/lwip/">Leon Woestenberg's lwIP page</a>
</ul>
Companies using lwIP in their products:
<ul>
<li>UK based <a href="http://www.tangentdevices.co.uk/">Tangent Devices Ltd</a> are incorporating lwIP in their film
and video post-production equipment.
<li><a href="http://www.axon.tv">Axon Digital Design BV</a> in The
Netherlands is merging lwIP with their current IP stack for use in the
Synapse modular broadcasting system.
</ul>
Projects using lwIP:
<ul>
<li><a href="http://www.cdt.luth.se/projects/arena/">The ARENA Project</a> - Hockey players equipped with pulse and breathing sensors running lwIP.<br>
<li><a href="http://bart.sm.luth.se/eis2001/">The Embedded Internet Systems 2001 Student Project</a> - Flow meter and belt tension sensors
running lwIP.<br>
<li><a href="http://dcdev.allusion.net/">KOS</a> - The KOS operating system for
Sega Dreamcast uses lwIP.<br>
</ul>
Other small TCP/IP implementations:
<ul>
<li><a href="http://dunkels.com/adam/uip/">uIP</a> - A very small TCP/IP
implementation, suitable for systems with hundreds of bytes free RAM
and a few kilobytes of free code space.<br>
<li><a href="http://ucip.sourceforge.net/">uC/IP</a> - uC/IP is a BSD-based
TCP/IP protocol stack for microcontrollers.<br>
<li><a href="http://liquorice.sourceforge.net">Liquorice</a> - Liquorice
includes a TCP/IP stack.<br>
<li><a href="http://www.nenie.org/cpcip/">CPC/IP</a> - A TCP/IP stack for
Amstrad CPCs.<br>
<li><a href="http://lng.sourceforge.net/">LUnix</a> - LUnix contains a small
TCP/IP stack.<br>
<li><a href="http://www.sweetcherrie.com/jolz64/jos/">JOS</a> - JOS includes a
TCP/IP implementation.<br>
<li><a href="http://www.csonline.net/bpaddock/tinytcp/default.htm">TinyTCP</a> - A very slim
TCP, IP, and FTP implementation.<br>
<li><a href="http://kyllikki.fluff.org/hardware/wwwpic2/">WWWpic2</a> - Small
HTTP/TCP/IP implementation for a PIC.<br>
<li><a href="http://www.rmbeales.fsnet.co.uk/files/html/picserver/picservd.htm">PIC Web Server</a> - Small HTTP/TCP/IP/SLIP PIC implementation.<br>
</ul>
Very small web servers:
<ul>
<li><a href="http://world.std.com/~fwhite/ace/">webACE</a> - World's Smallest
Web Server.<br>
<li><a href="http://www-ccs.cs.umass.edu/~shri/iPic.html">iPIC</a> - A Match
Head Sized Web Server.<br>
</ul>
Related RFCs:
<ul>
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc791.txt">Internet Protocol</a>, RFC791, September 1981.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc792.txt">Internet Control Message Protocol</a>, RFC792, September 1981.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc768.txt">User Datagram Protocol</a>, RFC768, August 1980.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc793.txt">Transmission Control Protocol</a>, RFC793, September 1981.
<li>D. D. Clark, <a
href="ftp://ftp.ietf.org/rfc/rfc813.txt">Window and Acknowledgement Strategy in TCP</a>, RFC813, July 1982.
<li>D. D. Clark, <a
href="ftp://ftp.ietf.org/rfc/rfc817.txt">Modularity and Efficiency in Protocol Implementation</a>, RFC817, July 1982.
<li>R. Braden, <a
href="ftp://ftp.ietf.org/rfc/rfc1122.txt">Requirements for Internet Hosts -- Communication Layers</a>, RFC1122, October 1989.
<li>T. Mallory and A. Kullberg, <a
href="ftp://ftp.ietf.org/rfc/rfc1141.txt">Incremental Updating of the Internet Checksum</a>, RFC1141, January 1990.
<li>A. Rijsinghani, <a
href="ftp://ftp.ietf.org/rfc/rfc1624.txt">Computation of the Internet Checksum via Incremental Update</a>, RFC1624, May 1994.
<li>R. Braden, <a
href="ftp://ftp.ietf.org/rfc/rfc1337.txt">TIME-WAIT Assasination Hazards in TCP</a>, RFC1337, May 1992.
<li>B. Carpenter, <a
href="ftp://ftp.ietf.org/rfc/rfc1958.txt">Architectural Principles of the Internet</a>, RFC1958, June 1996.
<li>M. Allman, V. Paxson and W. Stevens, <a
href="ftp://ftp.ietf.org/rfc/rfc2581.txt">TCP Congestion Control</a>, RFC2581, April 1999.
<li>S. Parker and C. Schmechel, <a
href="ftp://ftp.ietf.org/rfc/rfc2398.txt">Some Testing Tools for TCP Implementors</a>, RFC2398, August 1998.
</ul>
Related publications:
<ul>
<li>V. Jacobson. Congestion avoidance and control. In <i>Proceedings of
the SIGCOMM '88 Conference</i>, Stanford, California, August 1988.
<li>V. Jacobson. 4.3BSD TCP header prediction. <i>ACM Computer
Communications Review</i>, 20(2), April 1990.
<li>P. Karn and C. Partridge. Improving round-trip time estimates
in reliablie transport protocols. In <i>Proceedings of the SIGCOMM '87
Conference</i>, Stowe, Vermont, August 1987.
<li>J. Kay and J. Pasquale. Profiling and Reducing Processing
Overheads in TCP/IP. <i>IEEE/ACM Transactions of Networking</i>, 4(6), December 1996.
<li>L. Larzon, M. Degermark, and S. Pink. UDP Lite for
real-time multimedia applications. In <i>Proceedings of the IEEE
International Conference of Communications</i>, Vancouver, British
Columbia, Canada, June 1999.
<li>P. E. McKenney and K. F. Dove. Efcient demultiplexing of
incoming TCP packets. In <i>Proceedings of the SIGCOMM '92 Conference</i>, Baltimore, Maryland, August 1992.
<li>C. Partridge and S. Pink. A faster UDP. <i>IEEE/ACM Transactions
in Networking</i>, 1(4), August 1993.
</ul>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:02 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
[Links]
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,187 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Mailing list</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
[Mailing list]
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Mailing list</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<p align="justify">
The lwIP mailing list is the place to discuss lwIP. All topics related
to lwIP, such as porting or using lwIP, writing device drivers or
application programs for lwIP can be discussed here.
</p>
<h3>Archives</h3>
<p align="justify">
Archives can be found <a href="maillist/">here</a>.
</p>
<h3>Subscribe</h3>
<p align="justify">
To subscribe, send a mail to <a
href="mailto:majordomo@sics.se">majordomo@sics.se</a> with the message
<pre>
subscribe lwip
</pre>
in the message body. The subject should be kept blank.
</p>
<p align="justify">
In a few minutes, you should receive a welcome message and some
information regarding the subscription, including instructions for
unsubscribing. Save those messages for future reference.
</p>
<p align="justify">
You are now an lwIP mailing list subscriber!
</p>
<h3>Post</h3>
<p align="justify">
Posting to the lwIP mailing list is a simple as sending a mail to the
address <a href="mailto:lwip@sics.se">lwip@sics.se</a>.
</p>
<h3>Unsubscribe</h3>
<p align="justify">
To subscribe, send a mail to <a
href="mailto:majordomo@sics.se">majordomo@sics.se</a> with the message
<pre>
unsubscribe lwip
</pre>
in the message body. The subject should be kept blank.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:02 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
[Mailing list]
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,225 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - OS vs non-OS</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>OS vs non-OS</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<h2>Using lwIP with or without an operating system</h2>
<p align="justify">
There has been a few questions about how lwIP can be used in a
standalone environment (i.e., an environment without a multi-threaded
operating system) lately. The purpose of this document is to describe
how lwIP is designed to be used with and without a multi-threaded
operating system.
</p>
<center><img src="os.png"></center>
<h3>The lwIP single-threaded core</h3>
<p align="justify">
The core of lwIP consists of the actual implementations of the IP,
ICMP, UDP, and TCP protocols, as well as the support functions such as
buffer and memory management. The core components are the only ones
that are needed when lwIP is to be run in a single-threaded (non-OS)
environment.
</p>
<p align="justify">
The core components can be viewed as a software library which has the
following interface:
</p>
<ul>
<li><tt>ip_input(pbuf, netif)</tt>: Takes an IP packet and the incoming network
interface as arguments and does the TCP/IP processing for the packet.
<li><tt>tcp_tmr()</tt>: Should be called every 100 ms. Does all TCP
timer processing such as doing retransmissions.
</ul>
<p align="justify">
Because none of the core functions ever needs to block when run in a
single-threaded environment, the <tt>sys_arch</tt> (the operating
system abstraction layer) does not need to implement locking
semaphores or mailboxes. In future versions of lwIP, the dependancy of
the <tt>sys_arch</tt> will be removed in the single-threaded case.
</p>
<p align="justify">
A simple main loop for a single-threaded system might look
like this:
</p>
<pre>
while(1) {
if(poll_driver(netif) == PACKET_READY) {
pbuf = get_packet(netif);
ip_input(pbuf, netif);
}
if(clock() - last_time == 100 * CLOCK_MS) {
tcp_tmr();
last_time = clock();
}
}
</pre>
<h3>lwIP in a multi-threaded system</h3>
<p align="justify">
lwIP is designed to be able to be run in a multi-threaded system with
applications running in concurrent threads. The model used in this
case is that all TCP/IP processing is done in a single thread. The
application thread communicate with the TCP/IP thread using the
sequential API.
</p>
<center><img src="threads.png"></center>
<p align="justify">
The inter-thread communication is implemented in the two files
<tt>api_lib.c</tt> and <tt>api_msg.c</tt>. The former contains the
functions used by the application programs and the latter implements
the TCP/IP stack interface. A third file, <tt>tcpip.c</tt>, handles
incoming packets and timer events as described in the previous
section.
</p>
<p align="justify">
When run in a multi-threaded environment, incoming packets are handled
by the function <tt>tcpip_input()</tt>, which takes the same arguments
as the <tt>ip_input()</tt> function. The difference between the two
functions is that the <tt>tcpip_input()</tt> function does not process
the incoming packet immediately. It merely puts the packet on a queue
which later is drained by the TCP/IP thread.
</p>
<p align="justify">
When being run in a multi-threaded system, timer events are taken care
of internally in <tt>tcpip.c</tt>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:03 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

BIN
proj/unixsim/apps/fs/os.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

4188
proj/unixsim/apps/fsdata.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __FSDATA_H__
#define __FSDATA_H__
struct fsdata_file {
const struct fsdata_file *next;
const char *name;
const char *data;
const int len;
};
struct fsdata_file_noconst {
struct fsdata_file *next;
char *name;
char *data;
int len;
};
#endif /* __FSDATA_H__ */

244
proj/unixsim/apps/httpd.c Normal file
View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "httpd.h"
#include "lwip/tcp.h"
#include "fs.h"
struct http_state {
char *file;
u32_t left;
u8_t retries;
};
/*-----------------------------------------------------------------------------------*/
static void
conn_err(void *arg, err_t err)
{
struct http_state *hs;
hs = arg;
mem_free(hs);
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
mem_free(hs);
tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
err_t err;
u16_t len;
/* We cannot send more data than space avaliable in the send
buffer. */
if(tcp_sndbuf(pcb) < hs->left) {
len = tcp_sndbuf(pcb);
} else {
len = hs->left;
}
do {
err = tcp_write(pcb, hs->file, len, 0);
if(err == ERR_MEM) {
len /= 2;
}
} while(err == ERR_MEM && len > 1);
if(err == ERR_OK) {
hs->file += len;
hs->left -= len;
/* } else {
printf("send_data: error %s len %d %d\n", lwip_strerr(err), len, tcp_sndbuf(pcb));*/
}
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
struct http_state *hs;
hs = arg;
/* printf("Polll\n");*/
if(hs == NULL) {
/* printf("Null, close\n");*/
tcp_abort(pcb);
return ERR_ABRT;
} else {
++hs->retries;
if(hs->retries == 4) {
tcp_abort(pcb);
return ERR_ABRT;
}
send_data(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct http_state *hs;
hs = arg;
hs->retries = 0;
if(hs->left > 0) {
send_data(pcb, hs);
} else {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
int i;
char *data;
struct fs_file file;
struct http_state *hs;
hs = arg;
if(err == ERR_OK && p != NULL) {
/* Inform TCP that we have taken the data. */
tcp_recved(pcb, p->tot_len);
if(hs->file == NULL) {
data = p->payload;
if(strncmp(data, "GET ", 4) == 0) {
for(i = 0; i < 40; i++) {
if(((char *)data + 4)[i] == ' ' ||
((char *)data + 4)[i] == '\r' ||
((char *)data + 4)[i] == '\n') {
((char *)data + 4)[i] = 0;
}
}
if(*(char *)(data + 4) == '/' &&
*(char *)(data + 5) == 0) {
fs_open("/index.html", &file);
} else if(!fs_open((char *)data + 4, &file)) {
fs_open("/404.html", &file);
}
hs->file = file.data;
hs->left = file.len;
/* printf("data %p len %ld\n", hs->file, hs->left);*/
pbuf_free(p);
send_data(pcb, hs);
/* Tell TCP that we wish be to informed of data that has been
successfully sent by a call to the http_sent() function. */
tcp_sent(pcb, http_sent);
} else {
pbuf_free(p);
close_conn(pcb, hs);
}
} else {
pbuf_free(p);
}
}
if(err == ERR_OK && p == NULL) {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct http_state *hs;
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
hs = mem_malloc(sizeof(struct http_state));
if(hs == NULL) {
printf("http_accept: Out of memory\n");
return ERR_MEM;
}
/* Initialize the structure. */
hs->file = NULL;
hs->left = 0;
hs->retries = 0;
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, hs);
/* Tell TCP that we wish to be informed of incoming data by a call
to the http_recv() function. */
tcp_recv(pcb, http_recv);
tcp_err(pcb, conn_err);
tcp_poll(pcb, http_poll, 4);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 80);
pcb = tcp_listen(pcb);
tcp_accept(pcb, http_accept);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,10 +1,8 @@
/**
* @file
* This file is a posix wrapper for lwip/sockets.h.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +11,27 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __HTTPD_H__
#define __HTTPD_H__
#include "lwip/sockets.h"
void httpd_init(void);
#endif /* __HTTPD_H__ */

View File

@@ -53,7 +53,7 @@ while($file = <FILES>) {
$fvar = $file;
$fvar =~ s-/-_-g;
$fvar =~ s-\.-_-g;
print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
print(OUTPUT "static const char data".$fvar."[] = {\n");
print(OUTPUT "\t/* $file */\n\t");
for($j = 0; $j < length($file); $j++) {
printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
@@ -61,7 +61,7 @@ while($file = <FILES>) {
printf(OUTPUT "0,\n");
$i = 0;
$i = 0;
while(read(FILE, $data, 1)) {
if($i == 0) {
print(OUTPUT "\t");
@@ -94,4 +94,4 @@ for($i = 0; $i < @fvars; $i++) {
}
print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
print(OUTPUT "#define FS_NUMFILES $i\n");
print(OUTPUT "#define FS_NUMFILES $i");

1056
proj/unixsim/apps/shell.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,8 @@
/**
* @file
* This file is a posix wrapper for lwip/sockets.h.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +11,27 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __SHELL_H__
#define __SHELL_H__
#include "lwip/sockets.h"
void shell_init(void);
#endif /* __SHELL_H__ */

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/sys.h"
#include "lwip/api.h"
/*-----------------------------------------------------------------------------------*/
static void
tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
/* Bind connection to well known port number 7. */
netconn_bind(conn, NULL, 7);
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while(1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/*printf("accepted new connection %p\n", newconn);*/
/* Process the new connection. */
if(newconn != NULL) {
struct netbuf *buf;
void *data;
u16_t len;
while((buf = netconn_recv(newconn)) != NULL) {
/*printf("Recved\n");*/
do {
netbuf_data(buf, &data, &len);
err = netconn_write(newconn, data, len, NETCONN_COPY);
if(err != ERR_OK) {
/* printf("tcpecho: netconn_write: error \"%s\"\n", lwip_strerr(err));*/
}
} while(netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/*printf("Got EOF, looping\n");*/
/* Close connection and discard connection identifier. */
netconn_delete(newconn);
}
}
}
/*-----------------------------------------------------------------------------------*/
void
tcpecho_init(void)
{
sys_thread_new(tcpecho_thread, NULL);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,10 +1,8 @@
/**
* @file
* This file is a posix wrapper for lwip/netdb.h.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +11,28 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/netdb.h"
#ifndef __TCPECHO_H__
#define __TCPECHO_H__
void tcpecho_init(void);
#endif /* __TCPECHO_H__ */

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/api.h"
#include "lwip/sys.h"
/*-----------------------------------------------------------------------------------*/
void
udpecho_thread(void *arg)
{
static struct netconn *conn;
static struct netbuf *buf;
static struct ip_addr *addr;
static unsigned short port;
char buffer[4096];
conn = netconn_new(NETCONN_UDP);
netconn_bind(conn, NULL, 7);
while(1) {
buf = netconn_recv(conn);
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
netconn_connect(conn, addr, port);
netconn_send(conn, buf);
netbuf_copy(buf, buffer, sizeof(buffer));
printf("got %s\n", buffer);
netbuf_delete(buf);
}
}
/*-----------------------------------------------------------------------------------*/
void
udpecho_init(void)
{
sys_thread_new(udpecho_thread, NULL);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
@@ -26,15 +26,12 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __UDPECHO_H__
#define __UDPECHO_H__
#ifndef LWIP_HDR_TEST_SOCKETS_STRESSTEST
#define LWIP_HDR_TEST_SOCKETS_STRESSTEST
void udpecho_init(void);
void sockets_stresstest_init_loopback(int addr_family);
void sockets_stresstest_init_server(int addr_family, u16_t server_port);
void sockets_stresstest_init_client(const char *remote_ip, u16_t remote_port);
#endif /* LWIP_HDR_TEST_SOCKETS_STRESSTEST */
#endif /* __UDPECHO_H__ */

171
proj/unixsim/lwipopts.h Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 1
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 1600
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 16
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 5
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 16
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 3
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 4
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs. */
#define MEMP_NUM_API_MSG 8
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG 8
/* These two control is reclaimer functions should be compiled
in. Should always be turned on (1). */
#define MEM_RECLAIM 1
#define MEMP_RECLAIM 1
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 6
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
#define PBUF_LINK_HLEN 16
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 1
/* TCP Maximum segment size. */
#define TCP_MSS 128
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 256
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS
/* TCP receive window. */
#define TCP_WND 1024
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 1
/* If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 0
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK 1
/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
#define STATS
#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */
#endif /* __LWIPOPTS_H__ */

189
proj/unixsim/simhost.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/tapif.h"
#include "netif/tunif.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/pcapif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
netif_init();
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
#if LWIP_DHCP
{
struct netif *netif;
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
netif = netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input);
netif_set_default(netif);
dhcp_init();
dhcp_start(netif);
}
#else
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
/* netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));*/
netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));
#endif
/* Only used for testing purposes: */
/* IP4_ADDR(&gw, 193,10,66,1);
IP4_ADDR(&ipaddr, 193,10,66,107);
IP4_ADDR(&netmask, 255,255,252,0);
netif_add(&ipaddr, &netmask, &gw, pcapif_init,
tcpip_input);*/
IP4_ADDR(&gw, 127,0,0,1);
IP4_ADDR(&ipaddr, 127,0,0,1);
IP4_ADDR(&netmask, 255,0,0,0);
netif_add(&ipaddr, &netmask, &gw, loopif_init,
tcpip_input);
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
/* sys_timeout(5000, tcp_timeout, NULL);*/
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
/* Block for ever. */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/simhost.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

157
proj/unixsim/simnode.c Normal file
View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "netif/sioslipif.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
IP4_ADDR(&gw, 192,168,1,1);
IP4_ADDR(&ipaddr, 192,168,1,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, unixif_init_client,
tcpip_input));
/* netif_set_default(netif_add(&ipaddr, &netmask, &gw, sioslipif_init1,
tcpip_input)); */
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
sys_timeout(5000, tcp_timeout, NULL);
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/client.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

167
proj/unixsim/simrouter.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/tapif.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "netif/sioslipif.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));
IP4_ADDR(&gw, 192,168,1,1);
IP4_ADDR(&ipaddr, 192,168,1,1);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, unixif_init_server,
tcpip_input));
system("route add 192.168.1.1 192.168.0.2");
system("route add 192.168.1.2 192.168.0.2");
/*netif_set_default(netif_add(&ipaddr, &netmask, &gw, sioslipif_init1,
tcpip_input)); */
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
sys_timeout(5000, tcp_timeout, NULL);
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/client.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,12 +1,10 @@
api/ - The code for the high-level wrapper API. Not needed if
you use the lowel-level call-back/raw API.
api/ - The code for the API.
apps/ - Higher layer applications that are specifically programmed
with the lwIP low-level raw API.
core/ - The core of the TPC/IP stack; protocol implementations,
memory and buffer management, and the low-level raw API.
arch/ - Architectural specific files are kept here.
core/ - The core files including protocol implementations, memory
and buffer management etc.
include/ - lwIP include files.
netif/ - Generic network interface device drivers are kept here.

View File

@@ -1,279 +0,0 @@
# This file is indended to be included in end-user CMakeLists.txt
# include(/path/to/Filelists.cmake)
# It assumes the variable LWIP_DIR is defined pointing to the
# root path of lwIP sources.
#
# This file is NOT designed (on purpose) to be used as cmake
# subdir via add_subdirectory()
# The intention is to provide greater flexibility to users to
# create their own targets using the *_SRCS variables.
set(LWIP_VERSION_MAJOR "2")
set(LWIP_VERSION_MINOR "1")
set(LWIP_VERSION_REVISION "3")
# LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases
# LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions
# Numbers 1..31 are reserved for release candidates
set(LWIP_VERSION_RC "LWIP_RC_RELEASE")
if ("${LWIP_VERSION_RC}" STREQUAL "LWIP_RC_RELEASE")
set(LWIP_VERSION_STRING
"${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MINOR}.${LWIP_VERSION_REVISION}"
)
elseif ("${LWIP_VERSION_RC}" STREQUAL "LWIP_RC_DEVELOPMENT")
set(LWIP_VERSION_STRING
"${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MINOR}.${LWIP_VERSION_REVISION}.dev"
)
else ("${LWIP_VERSION_RC}" STREQUAL "LWIP_RC_RELEASE")
set(LWIP_VERSION_STRING
"${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MINOR}.${LWIP_VERSION_REVISION}.rc${LWIP_VERSION_RC}"
)
endif ("${LWIP_VERSION_RC}" STREQUAL "LWIP_RC_RELEASE")
# The minimum set of files needed for lwIP.
set(lwipcore_SRCS
${LWIP_DIR}/src/core/init.c
${LWIP_DIR}/src/core/def.c
${LWIP_DIR}/src/core/dns.c
${LWIP_DIR}/src/core/inet_chksum.c
${LWIP_DIR}/src/core/ip.c
${LWIP_DIR}/src/core/mem.c
${LWIP_DIR}/src/core/memp.c
${LWIP_DIR}/src/core/netif.c
${LWIP_DIR}/src/core/pbuf.c
${LWIP_DIR}/src/core/raw.c
${LWIP_DIR}/src/core/stats.c
${LWIP_DIR}/src/core/sys.c
${LWIP_DIR}/src/core/altcp.c
${LWIP_DIR}/src/core/altcp_alloc.c
${LWIP_DIR}/src/core/altcp_tcp.c
${LWIP_DIR}/src/core/tcp.c
${LWIP_DIR}/src/core/tcp_in.c
${LWIP_DIR}/src/core/tcp_out.c
${LWIP_DIR}/src/core/timeouts.c
${LWIP_DIR}/src/core/udp.c
)
set(lwipcore4_SRCS
${LWIP_DIR}/src/core/ipv4/autoip.c
${LWIP_DIR}/src/core/ipv4/dhcp.c
${LWIP_DIR}/src/core/ipv4/etharp.c
${LWIP_DIR}/src/core/ipv4/icmp.c
${LWIP_DIR}/src/core/ipv4/igmp.c
${LWIP_DIR}/src/core/ipv4/ip4_frag.c
${LWIP_DIR}/src/core/ipv4/ip4.c
${LWIP_DIR}/src/core/ipv4/ip4_addr.c
)
set(lwipcore6_SRCS
${LWIP_DIR}/src/core/ipv6/dhcp6.c
${LWIP_DIR}/src/core/ipv6/ethip6.c
${LWIP_DIR}/src/core/ipv6/icmp6.c
${LWIP_DIR}/src/core/ipv6/inet6.c
${LWIP_DIR}/src/core/ipv6/ip6.c
${LWIP_DIR}/src/core/ipv6/ip6_addr.c
${LWIP_DIR}/src/core/ipv6/ip6_frag.c
${LWIP_DIR}/src/core/ipv6/mld6.c
${LWIP_DIR}/src/core/ipv6/nd6.c
)
# APIFILES: The files which implement the sequential and socket APIs.
set(lwipapi_SRCS
${LWIP_DIR}/src/api/api_lib.c
${LWIP_DIR}/src/api/api_msg.c
${LWIP_DIR}/src/api/err.c
${LWIP_DIR}/src/api/if_api.c
${LWIP_DIR}/src/api/netbuf.c
${LWIP_DIR}/src/api/netdb.c
${LWIP_DIR}/src/api/netifapi.c
${LWIP_DIR}/src/api/sockets.c
${LWIP_DIR}/src/api/tcpip.c
)
# Files implementing various generic network interface functions
set(lwipnetif_SRCS
${LWIP_DIR}/src/netif/ethernet.c
${LWIP_DIR}/src/netif/bridgeif.c
${LWIP_DIR}/src/netif/bridgeif_fdb.c
${LWIP_DIR}/src/netif/slipif.c
)
# 6LoWPAN
set(lwipsixlowpan_SRCS
${LWIP_DIR}/src/netif/lowpan6_common.c
${LWIP_DIR}/src/netif/lowpan6.c
${LWIP_DIR}/src/netif/lowpan6_ble.c
${LWIP_DIR}/src/netif/zepif.c
)
# PPP
set(lwipppp_SRCS
${LWIP_DIR}/src/netif/ppp/auth.c
${LWIP_DIR}/src/netif/ppp/ccp.c
${LWIP_DIR}/src/netif/ppp/chap-md5.c
${LWIP_DIR}/src/netif/ppp/chap_ms.c
${LWIP_DIR}/src/netif/ppp/chap-new.c
${LWIP_DIR}/src/netif/ppp/demand.c
${LWIP_DIR}/src/netif/ppp/eap.c
${LWIP_DIR}/src/netif/ppp/ecp.c
${LWIP_DIR}/src/netif/ppp/eui64.c
${LWIP_DIR}/src/netif/ppp/fsm.c
${LWIP_DIR}/src/netif/ppp/ipcp.c
${LWIP_DIR}/src/netif/ppp/ipv6cp.c
${LWIP_DIR}/src/netif/ppp/lcp.c
${LWIP_DIR}/src/netif/ppp/magic.c
${LWIP_DIR}/src/netif/ppp/mppe.c
${LWIP_DIR}/src/netif/ppp/multilink.c
${LWIP_DIR}/src/netif/ppp/ppp.c
${LWIP_DIR}/src/netif/ppp/pppapi.c
${LWIP_DIR}/src/netif/ppp/pppcrypt.c
${LWIP_DIR}/src/netif/ppp/pppoe.c
${LWIP_DIR}/src/netif/ppp/pppol2tp.c
${LWIP_DIR}/src/netif/ppp/pppos.c
${LWIP_DIR}/src/netif/ppp/upap.c
${LWIP_DIR}/src/netif/ppp/utils.c
${LWIP_DIR}/src/netif/ppp/vj.c
${LWIP_DIR}/src/netif/ppp/polarssl/arc4.c
${LWIP_DIR}/src/netif/ppp/polarssl/des.c
${LWIP_DIR}/src/netif/ppp/polarssl/md4.c
${LWIP_DIR}/src/netif/ppp/polarssl/md5.c
${LWIP_DIR}/src/netif/ppp/polarssl/sha1.c
)
# SNMPv3 agent
set(lwipsnmp_SRCS
${LWIP_DIR}/src/apps/snmp/snmp_asn1.c
${LWIP_DIR}/src/apps/snmp/snmp_core.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_icmp.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_interfaces.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_ip.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_snmp.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_system.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_tcp.c
${LWIP_DIR}/src/apps/snmp/snmp_mib2_udp.c
${LWIP_DIR}/src/apps/snmp/snmp_snmpv2_framework.c
${LWIP_DIR}/src/apps/snmp/snmp_snmpv2_usm.c
${LWIP_DIR}/src/apps/snmp/snmp_msg.c
${LWIP_DIR}/src/apps/snmp/snmpv3.c
${LWIP_DIR}/src/apps/snmp/snmp_netconn.c
${LWIP_DIR}/src/apps/snmp/snmp_pbuf_stream.c
${LWIP_DIR}/src/apps/snmp/snmp_raw.c
${LWIP_DIR}/src/apps/snmp/snmp_scalar.c
${LWIP_DIR}/src/apps/snmp/snmp_table.c
${LWIP_DIR}/src/apps/snmp/snmp_threadsync.c
${LWIP_DIR}/src/apps/snmp/snmp_traps.c
)
# HTTP server + client
set(lwiphttp_SRCS
${LWIP_DIR}/src/apps/http/altcp_proxyconnect.c
${LWIP_DIR}/src/apps/http/fs.c
${LWIP_DIR}/src/apps/http/http_client.c
${LWIP_DIR}/src/apps/http/httpd.c
)
# MAKEFSDATA HTTP server host utility
set(lwipmakefsdata_SRCS
${LWIP_DIR}/src/apps/http/makefsdata/makefsdata.c
)
# IPERF server
set(lwipiperf_SRCS
${LWIP_DIR}/src/apps/lwiperf/lwiperf.c
)
# SMTP client
set(lwipsmtp_SRCS
${LWIP_DIR}/src/apps/smtp/smtp.c
)
# SNTP client
set(lwipsntp_SRCS
${LWIP_DIR}/src/apps/sntp/sntp.c
)
# MDNS responder
set(lwipmdns_SRCS
${LWIP_DIR}/src/apps/mdns/mdns.c
)
# NetBIOS name server
set(lwipnetbios_SRCS
${LWIP_DIR}/src/apps/netbiosns/netbiosns.c
)
# TFTP server files
set(lwiptftp_SRCS
${LWIP_DIR}/src/apps/tftp/tftp_server.c
)
# MQTT client files
set(lwipmqtt_SRCS
${LWIP_DIR}/src/apps/mqtt/mqtt.c
)
# ARM MBEDTLS related files of lwIP rep
set(lwipmbedtls_SRCS
${LWIP_DIR}/src/apps/altcp_tls/altcp_tls_mbedtls.c
${LWIP_DIR}/src/apps/altcp_tls/altcp_tls_mbedtls_mem.c
${LWIP_DIR}/src/apps/snmp/snmpv3_mbedtls.c
)
# All LWIP files without apps
set(lwipnoapps_SRCS
${lwipcore_SRCS}
${lwipcore4_SRCS}
${lwipcore6_SRCS}
${lwipapi_SRCS}
${lwipnetif_SRCS}
${lwipsixlowpan_SRCS}
${lwipppp_SRCS}
)
# LWIPAPPFILES: All LWIP APPs
set(lwipallapps_SRCS
${lwipsnmp_SRCS}
${lwiphttp_SRCS}
${lwipiperf_SRCS}
${lwipsmtp_SRCS}
${lwipsntp_SRCS}
${lwipmdns_SRCS}
${lwipnetbios_SRCS}
${lwiptftp_SRCS}
${lwipmqtt_SRCS}
${lwipmbedtls_SRCS}
)
# Generate lwip/init.h (version info)
configure_file(${LWIP_DIR}/src/include/lwip/init.h.cmake.in ${LWIP_DIR}/src/include/lwip/init.h)
# Documentation
set(DOXYGEN_DIR ${LWIP_DIR}/doc/doxygen)
set(DOXYGEN_OUTPUT_DIR output)
set(DOXYGEN_IN ${LWIP_DIR}/doc/doxygen/lwip.Doxyfile.cmake.in)
set(DOXYGEN_OUT ${LWIP_DIR}/doc/doxygen/lwip.Doxyfile)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT})
find_package(Doxygen)
if (DOXYGEN_FOUND)
message("Doxygen build started")
add_custom_target(lwipdocs
COMMAND ${CMAKE_COMMAND} -E remove_directory ${DOXYGEN_DIR}/${DOXYGEN_OUTPUT_DIR}/html
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${DOXYGEN_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
else (DOXYGEN_FOUND)
message("Doxygen needs to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
# lwIP libraries
add_library(lwipcore EXCLUDE_FROM_ALL ${lwipnoapps_SRCS})
target_compile_options(lwipcore PRIVATE ${LWIP_COMPILER_FLAGS})
target_compile_definitions(lwipcore PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
target_include_directories(lwipcore PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS})
add_library(lwipallapps EXCLUDE_FROM_ALL ${lwipallapps_SRCS})
target_compile_options(lwipallapps PRIVATE ${LWIP_COMPILER_FLAGS})
target_compile_definitions(lwipallapps PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
target_include_directories(lwipallapps PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS})

View File

@@ -1,205 +0,0 @@
#
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/init.c \
$(LWIPDIR)/core/def.c \
$(LWIPDIR)/core/dns.c \
$(LWIPDIR)/core/inet_chksum.c \
$(LWIPDIR)/core/ip.c \
$(LWIPDIR)/core/mem.c \
$(LWIPDIR)/core/memp.c \
$(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c \
$(LWIPDIR)/core/raw.c \
$(LWIPDIR)/core/stats.c \
$(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/altcp.c \
$(LWIPDIR)/core/altcp_alloc.c \
$(LWIPDIR)/core/altcp_tcp.c \
$(LWIPDIR)/core/tcp.c \
$(LWIPDIR)/core/tcp_in.c \
$(LWIPDIR)/core/tcp_out.c \
$(LWIPDIR)/core/timeouts.c \
$(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
$(LWIPDIR)/core/ipv4/dhcp.c \
$(LWIPDIR)/core/ipv4/etharp.c \
$(LWIPDIR)/core/ipv4/icmp.c \
$(LWIPDIR)/core/ipv4/igmp.c \
$(LWIPDIR)/core/ipv4/ip4_frag.c \
$(LWIPDIR)/core/ipv4/ip4.c \
$(LWIPDIR)/core/ipv4/ip4_addr.c
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
$(LWIPDIR)/core/ipv6/ethip6.c \
$(LWIPDIR)/core/ipv6/icmp6.c \
$(LWIPDIR)/core/ipv6/inet6.c \
$(LWIPDIR)/core/ipv6/ip6.c \
$(LWIPDIR)/core/ipv6/ip6_addr.c \
$(LWIPDIR)/core/ipv6/ip6_frag.c \
$(LWIPDIR)/core/ipv6/mld6.c \
$(LWIPDIR)/core/ipv6/nd6.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c \
$(LWIPDIR)/api/api_msg.c \
$(LWIPDIR)/api/err.c \
$(LWIPDIR)/api/if_api.c \
$(LWIPDIR)/api/netbuf.c \
$(LWIPDIR)/api/netdb.c \
$(LWIPDIR)/api/netifapi.c \
$(LWIPDIR)/api/sockets.c \
$(LWIPDIR)/api/tcpip.c
# NETIFFILES: Files implementing various generic network interface functions
NETIFFILES=$(LWIPDIR)/netif/ethernet.c \
$(LWIPDIR)/netif/bridgeif.c \
$(LWIPDIR)/netif/bridgeif_fdb.c \
$(LWIPDIR)/netif/slipif.c
# SIXLOWPAN: 6LoWPAN
SIXLOWPAN=$(LWIPDIR)/netif/lowpan6_common.c \
$(LWIPDIR)/netif/lowpan6.c \
$(LWIPDIR)/netif/lowpan6_ble.c \
$(LWIPDIR)/netif/zepif.c
# PPPFILES: PPP
PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \
$(LWIPDIR)/netif/ppp/ccp.c \
$(LWIPDIR)/netif/ppp/chap-md5.c \
$(LWIPDIR)/netif/ppp/chap_ms.c \
$(LWIPDIR)/netif/ppp/chap-new.c \
$(LWIPDIR)/netif/ppp/demand.c \
$(LWIPDIR)/netif/ppp/eap.c \
$(LWIPDIR)/netif/ppp/ecp.c \
$(LWIPDIR)/netif/ppp/eui64.c \
$(LWIPDIR)/netif/ppp/fsm.c \
$(LWIPDIR)/netif/ppp/ipcp.c \
$(LWIPDIR)/netif/ppp/ipv6cp.c \
$(LWIPDIR)/netif/ppp/lcp.c \
$(LWIPDIR)/netif/ppp/magic.c \
$(LWIPDIR)/netif/ppp/mppe.c \
$(LWIPDIR)/netif/ppp/multilink.c \
$(LWIPDIR)/netif/ppp/ppp.c \
$(LWIPDIR)/netif/ppp/pppapi.c \
$(LWIPDIR)/netif/ppp/pppcrypt.c \
$(LWIPDIR)/netif/ppp/pppoe.c \
$(LWIPDIR)/netif/ppp/pppol2tp.c \
$(LWIPDIR)/netif/ppp/pppos.c \
$(LWIPDIR)/netif/ppp/upap.c \
$(LWIPDIR)/netif/ppp/utils.c \
$(LWIPDIR)/netif/ppp/vj.c \
$(LWIPDIR)/netif/ppp/polarssl/arc4.c \
$(LWIPDIR)/netif/ppp/polarssl/des.c \
$(LWIPDIR)/netif/ppp/polarssl/md4.c \
$(LWIPDIR)/netif/ppp/polarssl/md5.c \
$(LWIPDIR)/netif/ppp/polarssl/sha1.c
# LWIPNOAPPSFILES: All LWIP files without apps
LWIPNOAPPSFILES=$(COREFILES) \
$(CORE4FILES) \
$(CORE6FILES) \
$(APIFILES) \
$(NETIFFILES) \
$(PPPFILES) \
$(SIXLOWPAN)
# SNMPFILES: SNMPv2c agent
SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \
$(LWIPDIR)/apps/snmp/snmp_core.c \
$(LWIPDIR)/apps/snmp/snmp_mib2.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_system.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \
$(LWIPDIR)/apps/snmp/snmp_snmpv2_framework.c \
$(LWIPDIR)/apps/snmp/snmp_snmpv2_usm.c \
$(LWIPDIR)/apps/snmp/snmp_msg.c \
$(LWIPDIR)/apps/snmp/snmpv3.c \
$(LWIPDIR)/apps/snmp/snmp_netconn.c \
$(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \
$(LWIPDIR)/apps/snmp/snmp_raw.c \
$(LWIPDIR)/apps/snmp/snmp_scalar.c \
$(LWIPDIR)/apps/snmp/snmp_table.c \
$(LWIPDIR)/apps/snmp/snmp_threadsync.c \
$(LWIPDIR)/apps/snmp/snmp_traps.c
# HTTPFILES: HTTP server + client
HTTPFILES=$(LWIPDIR)/apps/http/altcp_proxyconnect.c \
$(LWIPDIR)/apps/http/fs.c \
$(LWIPDIR)/apps/http/http_client.c \
$(LWIPDIR)/apps/http/httpd.c
# MAKEFSDATA: MAKEFSDATA HTTP server host utility
MAKEFSDATAFILES=$(LWIPDIR)/apps/http/makefsdata/makefsdata.c
# LWIPERFFILES: IPERF server
LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
# SMTPFILES: SMTP client
SMTPFILES=$(LWIPDIR)/apps/smtp/smtp.c
# SNTPFILES: SNTP client
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
# MDNSFILES: MDNS responder
MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
# NETBIOSNSFILES: NetBIOS name server
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
# TFTPFILES: TFTP server files
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
# MQTTFILES: MQTT client files
MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c
# MBEDTLS_FILES: MBEDTLS related files of lwIP rep
MBEDTLS_FILES=$(LWIPDIR)/apps/altcp_tls/altcp_tls_mbedtls.c \
$(LWIPDIR)/apps/altcp_tls/altcp_tls_mbedtls_mem.c \
$(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c
# LWIPAPPFILES: All LWIP APPs
LWIPAPPFILES=$(SNMPFILES) \
$(HTTPFILES) \
$(LWIPERFFILES) \
$(SMTPFILES) \
$(SNTPFILES) \
$(MDNSFILES) \
$(NETBIOSNSFILES) \
$(TFTPFILES) \
$(MQTTFILES) \
$(MBEDTLS_FILES)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,8 @@
/**
* @file
* Error Management module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -17,99 +11,49 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/err.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/errno.h"
#if !NO_SYS
/** Table to quickly map an lwIP error (err_t) to a socket error
* by using -err as an index */
static const int err_to_errno_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
EINVAL, /* ERR_VAL -6 Illegal value. */
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
EADDRINUSE, /* ERR_USE -8 Address in use. */
EALREADY, /* ERR_ALREADY -9 Already connecting. */
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
ENOTCONN, /* ERR_CONN -11 Not connected. */
-1, /* ERR_IF -12 Low-level netif error */
ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
ECONNRESET, /* ERR_RST -14 Connection reset. */
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
EIO /* ERR_ARG -16 Illegal argument. */
};
int
err_to_errno(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
return EIO;
}
return err_to_errno_table[-err];
}
#endif /* !NO_SYS */
#ifdef LWIP_DEBUG
static const char *err_strerr[] = {
"Ok.", /* ERR_OK 0 */
"Out of memory error.", /* ERR_MEM -1 */
"Buffer error.", /* ERR_BUF -2 */
"Timeout.", /* ERR_TIMEOUT -3 */
"Routing problem.", /* ERR_RTE -4 */
"Operation in progress.", /* ERR_INPROGRESS -5 */
"Illegal value.", /* ERR_VAL -6 */
"Operation would block.", /* ERR_WOULDBLOCK -7 */
"Address in use.", /* ERR_USE -8 */
"Already connecting.", /* ERR_ALREADY -9 */
"Already connected.", /* ERR_ISCONN -10 */
"Not connected.", /* ERR_CONN -11 */
"Low-level netif error.", /* ERR_IF -12 */
"Connection aborted.", /* ERR_ABRT -13 */
"Connection reset.", /* ERR_RST -14 */
"Connection closed.", /* ERR_CLSD -15 */
"Illegal argument." /* ERR_ARG -16 */
static char *err_strerr[] = {"Ok.",
"Out of memory error.",
"Buffer error.",
"Connection aborted.",
"Connection reset.",
"Connection closed.",
"Not connected.",
"Illegal value.",
"Illegal argument.",
"Routing problem.",
"Address in use."
};
/**
* Convert an lwip internal error to a string representation.
*
* @param err an lwip internal err_t
* @return a string representation for err
*/
const char *
/*-----------------------------------------------------------------------------------*/
char *
lwip_strerr(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) {
return "Unknown error.";
}
return err_strerr[-err];
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */

View File

@@ -1,102 +0,0 @@
/**
* @file
* Interface Identification APIs from:
* RFC 3493: Basic Socket Interface Extensions for IPv6
* Section 4: Interface Identification
*
* @defgroup if_api Interface Identification API
* @ingroup socket
*/
/*
* Copyright (c) 2017 Joel Cunningham, Garmin International, Inc. <joel.cunningham@garmin.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Joel Cunningham <joel.cunningham@me.com>
*
*/
#include "lwip/opt.h"
#if LWIP_SOCKET
#include "lwip/errno.h"
#include "lwip/if_api.h"
#include "lwip/netifapi.h"
#include "lwip/priv/sockets_priv.h"
/**
* @ingroup if_api
* Maps an interface index to its corresponding name.
* @param ifindex interface index
* @param ifname shall point to a buffer of at least {IF_NAMESIZE} bytes
* @return If ifindex is an interface index, then the function shall return the
* value supplied in ifname, which points to a buffer now containing the interface name.
* Otherwise, the function shall return a NULL pointer.
*/
char *
lwip_if_indextoname(unsigned int ifindex, char *ifname)
{
#if LWIP_NETIF_API
if (ifindex <= 0xff) {
err_t err = netifapi_netif_index_to_name((u8_t)ifindex, ifname);
if (!err && ifname[0] != '\0') {
return ifname;
}
}
#else /* LWIP_NETIF_API */
LWIP_UNUSED_ARG(ifindex);
LWIP_UNUSED_ARG(ifname);
#endif /* LWIP_NETIF_API */
set_errno(ENXIO);
return NULL;
}
/**
* @ingroup if_api
* Returs the interface index corresponding to name ifname.
* @param ifname Interface name
* @return The corresponding index if ifname is the name of an interface;
* otherwise, zero.
*/
unsigned int
lwip_if_nametoindex(const char *ifname)
{
#if LWIP_NETIF_API
err_t err;
u8_t idx;
err = netifapi_netif_name_to_index(ifname, &idx);
if (!err) {
return idx;
}
#else /* LWIP_NETIF_API */
LWIP_UNUSED_ARG(ifname);
#endif /* LWIP_NETIF_API */
return 0; /* invalid index */
}
#endif /* LWIP_SOCKET */

View File

@@ -1,250 +0,0 @@
/**
* @file
* Network buffer management
*
* @defgroup netbuf Network buffers
* @ingroup netconn
* Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
* to avoid copying data around.\n
* Buffers must not be shared accross multiple threads, all functions except
* netbuf_new() and netbuf_delete() are not thread-safe.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
#include "lwip/netbuf.h"
#include "lwip/memp.h"
#include <string.h>
/**
* @ingroup netbuf
* Create (allocate) and initialize a new netbuf.
* The netbuf doesn't yet contain a packet buffer!
*
* @return a pointer to a new netbuf
* NULL on lack of memory
*/
struct
netbuf *netbuf_new(void)
{
struct netbuf *buf;
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf != NULL) {
memset(buf, 0, sizeof(struct netbuf));
}
return buf;
}
/**
* @ingroup netbuf
* Deallocate a netbuf allocated by netbuf_new().
*
* @param buf pointer to a netbuf allocated by netbuf_new()
*/
void
netbuf_delete(struct netbuf *buf)
{
if (buf != NULL) {
if (buf->p != NULL) {
pbuf_free(buf->p);
buf->p = buf->ptr = NULL;
}
memp_free(MEMP_NETBUF, buf);
}
}
/**
* @ingroup netbuf
* Allocate memory for a packet buffer for a given netbuf.
*
* @param buf the netbuf for which to allocate a packet buffer
* @param size the size of the packet buffer to allocate
* @return pointer to the allocated memory
* NULL if no memory could be allocated
*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
/* Deallocate any previously allocated memory. */
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
if (buf->p == NULL) {
return NULL;
}
LWIP_ASSERT("check that first pbuf can hold size",
(buf->p->len >= size));
buf->ptr = buf->p;
return buf->p->payload;
}
/**
* @ingroup netbuf
* Free the packet buffer included in a netbuf
*
* @param buf pointer to the netbuf which contains the packet buffer to free
*/
void
netbuf_free(struct netbuf *buf)
{
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = buf->ptr = NULL;
#if LWIP_CHECKSUM_ON_COPY
buf->flags = 0;
buf->toport_chksum = 0;
#endif /* LWIP_CHECKSUM_ON_COPY */
}
/**
* @ingroup netbuf
* Let a netbuf reference existing (non-volatile) data.
*
* @param buf netbuf which should reference the data
* @param dataptr pointer to the data to reference
* @param size size of the data
* @return ERR_OK if data is referenced
* ERR_MEM if data couldn't be referenced due to lack of memory
*/
err_t
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
{
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
if (buf->p == NULL) {
buf->ptr = NULL;
return ERR_MEM;
}
((struct pbuf_rom *)buf->p)->payload = dataptr;
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
return ERR_OK;
}
/**
* @ingroup netbuf
* Chain one netbuf to another (@see pbuf_chain)
*
* @param head the first netbuf
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
pbuf_cat(head->p, tail->p);
head->ptr = head->p;
memp_free(MEMP_NETBUF, tail);
}
/**
* @ingroup netbuf
* Get the data pointer and length of the data inside a netbuf.
*
* @param buf netbuf to get the data from
* @param dataptr pointer to a void pointer where to store the data pointer
* @param len pointer to an u16_t where the length of the data is stored
* @return ERR_OK if the information was retrieved,
* ERR_BUF on error.
*/
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
if (buf->ptr == NULL) {
return ERR_BUF;
}
*dataptr = buf->ptr->payload;
*len = buf->ptr->len;
return ERR_OK;
}
/**
* @ingroup netbuf
* Move the current data pointer of a packet buffer contained in a netbuf
* to the next part.
* The packet buffer itself is not modified.
*
* @param buf the netbuf to modify
* @return -1 if there is no next part
* 1 if moved to the next part but now there is no next part
* 0 if moved to the next part and there are still more parts
*/
s8_t
netbuf_next(struct netbuf *buf)
{
LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
if (buf->ptr->next == NULL) {
return -1;
}
buf->ptr = buf->ptr->next;
if (buf->ptr->next == NULL) {
return 1;
}
return 0;
}
/**
* @ingroup netbuf
* Move the current data pointer of a packet buffer contained in a netbuf
* to the beginning of the packet.
* The packet buffer itself is not modified.
*
* @param buf the netbuf to modify
*/
void
netbuf_first(struct netbuf *buf)
{
LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
buf->ptr = buf->p;
}
#endif /* LWIP_NETCONN */

View File

@@ -1,417 +0,0 @@
/**
* @file
* API functions for name resolving
*
* @defgroup netdbapi NETDB API
* @ingroup socket
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#include "lwip/netdb.h"
#if LWIP_DNS && LWIP_SOCKET
#include "lwip/err.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/ip_addr.h"
#include "lwip/api.h"
#include "lwip/dns.h"
#include <string.h> /* memset */
#include <stdlib.h> /* atoi */
/** helper struct for gethostbyname_r to access the char* buffer */
struct gethostbyname_r_helper {
ip_addr_t *addr_list[2];
ip_addr_t addr;
char *aliases;
};
/** h_errno is exported in netdb.h for access by applications. */
#if LWIP_DNS_API_DECLARE_H_ERRNO
int h_errno;
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
#define LWIP_DNS_API_HOSTENT_STORAGE 0
#endif
/** define "hostent" variables storage */
#if LWIP_DNS_API_HOSTENT_STORAGE
#define HOSTENT_STORAGE
#else
#define HOSTENT_STORAGE static
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
/**
* Returns an entry containing addresses of address family AF_INET
* for the host with name name.
* Due to dns_gethostbyname limitations, only one address is returned.
*
* @param name the hostname to resolve
* @return an entry containing addresses of address family AF_INET
* for the host with name name
*/
struct hostent *
lwip_gethostbyname(const char *name)
{
err_t err;
ip_addr_t addr;
/* buffer variables for lwip_gethostbyname() */
HOSTENT_STORAGE struct hostent s_hostent;
HOSTENT_STORAGE char *s_aliases;
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
/* query host IP address */
err = netconn_gethostbyname(name, &addr);
if (err != ERR_OK) {
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
h_errno = HOST_NOT_FOUND;
return NULL;
}
/* fill hostent */
s_hostent_addr = addr;
s_phostent_addr[0] = &s_hostent_addr;
s_phostent_addr[1] = NULL;
strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
s_hostname[DNS_MAX_NAME_LENGTH] = 0;
s_hostent.h_name = s_hostname;
s_aliases = NULL;
s_hostent.h_aliases = &s_aliases;
s_hostent.h_addrtype = AF_INET;
s_hostent.h_length = sizeof(ip_addr_t);
s_hostent.h_addr_list = (char **)&s_phostent_addr;
#if DNS_DEBUG
/* dump hostent */
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void *)s_hostent.h_aliases));
/* h_aliases are always empty */
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void *)s_hostent.h_addr_list));
if (s_hostent.h_addr_list != NULL) {
u8_t idx;
for (idx = 0; s_hostent.h_addr_list[idx]; idx++) {
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa(s_phostent_addr[idx])));
}
}
#endif /* DNS_DEBUG */
#if LWIP_DNS_API_HOSTENT_STORAGE
/* this function should return the "per-thread" hostent after copy from s_hostent */
return sys_thread_hostent(&s_hostent);
#else
return &s_hostent;
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
}
/**
* Thread-safe variant of lwip_gethostbyname: instead of using a static
* buffer, this function takes buffer and errno pointers as arguments
* and uses these for the result.
*
* @param name the hostname to resolve
* @param ret pre-allocated struct where to store the result
* @param buf pre-allocated buffer where to store additional data
* @param buflen the size of buf
* @param result pointer to a hostent pointer that is set to ret on success
* and set to zero on error
* @param h_errnop pointer to an int where to store errors (instead of modifying
* the global h_errno)
* @return 0 on success, non-zero on error, additional error information
* is stored in *h_errnop instead of h_errno to be thread-safe
*/
int
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
size_t buflen, struct hostent **result, int *h_errnop)
{
err_t err;
struct gethostbyname_r_helper *h;
char *hostname;
size_t namelen;
int lh_errno;
if (h_errnop == NULL) {
/* ensure h_errnop is never NULL */
h_errnop = &lh_errno;
}
if (result == NULL) {
/* not all arguments given */
*h_errnop = EINVAL;
return -1;
}
/* first thing to do: set *result to nothing */
*result = NULL;
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
/* not all arguments given */
*h_errnop = EINVAL;
return -1;
}
namelen = strlen(name);
if (buflen < (sizeof(struct gethostbyname_r_helper) + LWIP_MEM_ALIGN_BUFFER(namelen + 1))) {
/* buf can't hold the data needed + a copy of name */
*h_errnop = ERANGE;
return -1;
}
h = (struct gethostbyname_r_helper *)LWIP_MEM_ALIGN(buf);
hostname = ((char *)h) + sizeof(struct gethostbyname_r_helper);
/* query host IP address */
err = netconn_gethostbyname(name, &h->addr);
if (err != ERR_OK) {
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
*h_errnop = HOST_NOT_FOUND;
return -1;
}
/* copy the hostname into buf */
MEMCPY(hostname, name, namelen);
hostname[namelen] = 0;
/* fill hostent */
h->addr_list[0] = &h->addr;
h->addr_list[1] = NULL;
h->aliases = NULL;
ret->h_name = hostname;
ret->h_aliases = &h->aliases;
ret->h_addrtype = AF_INET;
ret->h_length = sizeof(ip_addr_t);
ret->h_addr_list = (char **)&h->addr_list;
/* set result != NULL */
*result = ret;
/* return success */
return 0;
}
/**
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
* any additional storage associated with those structures. If the ai_next field
* of the structure is not null, the entire list of structures is freed.
*
* @param ai struct addrinfo to free
*/
void
lwip_freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next;
while (ai != NULL) {
next = ai->ai_next;
memp_free(MEMP_NETDB, ai);
ai = next;
}
}
/**
* Translates the name of a service location (for example, a host name) and/or
* a service name and returns a set of socket addresses and associated
* information to be used in creating a socket with which to address the
* specified service.
* Memory for the result is allocated internally and must be freed by calling
* lwip_freeaddrinfo()!
*
* Due to a limitation in dns_gethostbyname, only the first address of a
* host is returned.
* Also, service names are not supported (only port numbers)!
*
* @param nodename descriptive name or address string of the host
* (may be NULL -> local address)
* @param servname port number as string of NULL
* @param hints structure containing input values that set socktype and protocol
* @param res pointer to a pointer where to store the result (set to NULL on failure)
* @return 0 on success, non-zero on failure
*
* @todo: implement AI_V4MAPPED, AI_ADDRCONFIG
*/
int
lwip_getaddrinfo(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
err_t err;
ip_addr_t addr;
struct addrinfo *ai;
struct sockaddr_storage *sa = NULL;
int port_nr = 0;
size_t total_size;
size_t namelen = 0;
int ai_family;
if (res == NULL) {
return EAI_FAIL;
}
*res = NULL;
if ((nodename == NULL) && (servname == NULL)) {
return EAI_NONAME;
}
if (hints != NULL) {
ai_family = hints->ai_family;
if ((ai_family != AF_UNSPEC)
#if LWIP_IPV4
&& (ai_family != AF_INET)
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
&& (ai_family != AF_INET6)
#endif /* LWIP_IPV6 */
) {
return EAI_FAMILY;
}
} else {
ai_family = AF_UNSPEC;
}
if (servname != NULL) {
/* service name specified: convert to port number
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
port_nr = atoi(servname);
if (port_nr == 0 && (servname[0] != '0')) {
/* atoi failed - service was not numeric */
return EAI_SERVICE;
}
if ((port_nr < 0) || (port_nr > 0xffff)) {
return EAI_SERVICE;
}
}
if (nodename != NULL) {
/* service location specified, try to resolve */
if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
/* no DNS lookup, just parse for an address string */
if (!ipaddr_aton(nodename, &addr)) {
return EAI_NONAME;
}
#if LWIP_IPV4 && LWIP_IPV6
if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
(IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) {
return EAI_NONAME;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
} else {
#if LWIP_IPV4 && LWIP_IPV6
/* AF_UNSPEC: prefer IPv4 */
u8_t type = NETCONN_DNS_IPV4_IPV6;
if (ai_family == AF_INET) {
type = NETCONN_DNS_IPV4;
} else if (ai_family == AF_INET6) {
type = NETCONN_DNS_IPV6;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
if (err != ERR_OK) {
return EAI_FAIL;
}
}
} else {
/* service location specified, use loopback address */
if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
ip_addr_set_any_val(ai_family == AF_INET6, addr);
} else {
ip_addr_set_loopback_val(ai_family == AF_INET6, addr);
}
}
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
if (nodename != NULL) {
namelen = strlen(nodename);
if (namelen > DNS_MAX_NAME_LENGTH) {
/* invalid name length */
return EAI_FAIL;
}
LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
total_size += namelen + 1;
}
/* If this fails, please report to lwip-devel! :-) */
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
total_size <= NETDB_ELEM_SIZE);
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
if (ai == NULL) {
return EAI_MEMORY;
}
memset(ai, 0, total_size);
/* cast through void* to get rid of alignment warnings */
sa = (struct sockaddr_storage *)(void *)((u8_t *)ai + sizeof(struct addrinfo));
if (IP_IS_V6_VAL(addr)) {
#if LWIP_IPV6
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
/* set up sockaddr */
inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
sa6->sin6_family = AF_INET6;
sa6->sin6_len = sizeof(struct sockaddr_in6);
sa6->sin6_port = lwip_htons((u16_t)port_nr);
sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr));
ai->ai_family = AF_INET6;
#endif /* LWIP_IPV6 */
} else {
#if LWIP_IPV4
struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
/* set up sockaddr */
inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr));
sa4->sin_family = AF_INET;
sa4->sin_len = sizeof(struct sockaddr_in);
sa4->sin_port = lwip_htons((u16_t)port_nr);
ai->ai_family = AF_INET;
#endif /* LWIP_IPV4 */
}
/* set up addrinfo */
if (hints != NULL) {
/* copy socktype & protocol from hints if specified */
ai->ai_socktype = hints->ai_socktype;
ai->ai_protocol = hints->ai_protocol;
}
if (nodename != NULL) {
/* copy nodename to canonname if specified */
ai->ai_canonname = ((char *)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
MEMCPY(ai->ai_canonname, nodename, namelen);
ai->ai_canonname[namelen] = 0;
}
ai->ai_addrlen = sizeof(struct sockaddr_storage);
ai->ai_addr = (struct sockaddr *)sa;
*res = ai;
return 0;
}
#endif /* LWIP_DNS && LWIP_SOCKET */

View File

@@ -1,380 +0,0 @@
/**
* @file
* Network Interface Sequential API module
*
* @defgroup netifapi NETIF API
* @ingroup sequential_api
* Thread-safe functions to be called from non-TCPIP threads
*
* @defgroup netifapi_netif NETIF related
* @ingroup netifapi
* To be called from non-TCPIP threads
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#include "lwip/opt.h"
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
#include "lwip/etharp.h"
#include "lwip/netifapi.h"
#include "lwip/memp.h"
#include "lwip/priv/tcpip_priv.h"
#include <string.h> /* strncpy */
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name)
#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
/**
* Call netif_add() inside the tcpip_thread context.
*/
static err_t
netifapi_do_netif_add(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
if (!netif_add( msg->netif,
#if LWIP_IPV4
API_EXPR_REF(msg->msg.add.ipaddr),
API_EXPR_REF(msg->msg.add.netmask),
API_EXPR_REF(msg->msg.add.gw),
#endif /* LWIP_IPV4 */
msg->msg.add.state,
msg->msg.add.init,
msg->msg.add.input)) {
return ERR_IF;
} else {
return ERR_OK;
}
}
#if LWIP_IPV4
/**
* Call netif_set_addr() inside the tcpip_thread context.
*/
static err_t
netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
netif_set_addr( msg->netif,
API_EXPR_REF(msg->msg.add.ipaddr),
API_EXPR_REF(msg->msg.add.netmask),
API_EXPR_REF(msg->msg.add.gw));
return ERR_OK;
}
#endif /* LWIP_IPV4 */
/**
* Call netif_name_to_index() inside the tcpip_thread context.
*/
static err_t
netifapi_do_name_to_index(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
msg->msg.ifs.index = netif_name_to_index(msg->msg.ifs.name);
return ERR_OK;
}
/**
* Call netif_index_to_name() inside the tcpip_thread context.
*/
static err_t
netifapi_do_index_to_name(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) {
/* return failure via empty name */
msg->msg.ifs.name[0] = '\0';
}
return ERR_OK;
}
/**
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
* tcpip_thread context.
*/
static err_t
netifapi_do_netif_common(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
if (msg->msg.common.errtfunc != NULL) {
return msg->msg.common.errtfunc(msg->netif);
} else {
msg->msg.common.voidfunc(msg->netif);
return ERR_OK;
}
}
#if LWIP_ARP && LWIP_IPV4
/**
* @ingroup netifapi_arp
* Add or update an entry in the ARP cache.
* For an update, ipaddr is used to find the cache entry.
*
* @param ipaddr IPv4 address of cache entry
* @param ethaddr hardware address mapped to ipaddr
* @param type type of ARP cache entry
* @return ERR_OK: entry added/updated, else error from err_t
*/
err_t
netifapi_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netifapi_arp_entry type)
{
err_t err;
/* We only support permanent entries currently */
LWIP_UNUSED_ARG(type);
#if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING
LOCK_TCPIP_CORE();
err = etharp_add_static_entry(ipaddr, ethaddr);
UNLOCK_TCPIP_CORE();
#else
/* @todo add new vars to struct netifapi_msg and create a 'do' func */
LWIP_UNUSED_ARG(ipaddr);
LWIP_UNUSED_ARG(ethaddr);
err = ERR_VAL;
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */
return err;
}
/**
* @ingroup netifapi_arp
* Remove an entry in the ARP cache identified by ipaddr
*
* @param ipaddr IPv4 address of cache entry
* @param type type of ARP cache entry
* @return ERR_OK: entry removed, else error from err_t
*/
err_t
netifapi_arp_remove(const ip4_addr_t *ipaddr, enum netifapi_arp_entry type)
{
err_t err;
/* We only support permanent entries currently */
LWIP_UNUSED_ARG(type);
#if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING
LOCK_TCPIP_CORE();
err = etharp_remove_static_entry(ipaddr);
UNLOCK_TCPIP_CORE();
#else
/* @todo add new vars to struct netifapi_msg and create a 'do' func */
LWIP_UNUSED_ARG(ipaddr);
err = ERR_VAL;
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */
return err;
}
#endif /* LWIP_ARP && LWIP_IPV4 */
/**
* @ingroup netifapi_netif
* Call netif_add() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @note for params @see netif_add()
*/
err_t
netifapi_netif_add(struct netif *netif,
#if LWIP_IPV4
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
#endif /* LWIP_IPV4 */
void *state, netif_init_fn init, netif_input_fn input)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
#if LWIP_IPV4
if (ipaddr == NULL) {
ipaddr = IP4_ADDR_ANY4;
}
if (netmask == NULL) {
netmask = IP4_ADDR_ANY4;
}
if (gw == NULL) {
gw = IP4_ADDR_ANY4;
}
#endif /* LWIP_IPV4 */
NETIFAPI_VAR_REF(msg).netif = netif;
#if LWIP_IPV4
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
#endif /* LWIP_IPV4 */
NETIFAPI_VAR_REF(msg).msg.add.state = state;
NETIFAPI_VAR_REF(msg).msg.add.init = init;
NETIFAPI_VAR_REF(msg).msg.add.input = input;
err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
#if LWIP_IPV4
/**
* @ingroup netifapi_netif
* Call netif_set_addr() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @note for params @see netif_set_addr()
*/
err_t
netifapi_netif_set_addr(struct netif *netif,
const ip4_addr_t *ipaddr,
const ip4_addr_t *netmask,
const ip4_addr_t *gw)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
if (ipaddr == NULL) {
ipaddr = IP4_ADDR_ANY4;
}
if (netmask == NULL) {
netmask = IP4_ADDR_ANY4;
}
if (gw == NULL) {
gw = IP4_ADDR_ANY4;
}
NETIFAPI_VAR_REF(msg).netif = netif;
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
#endif /* LWIP_IPV4 */
/**
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
* way by running that function inside the tcpip_thread context.
*
* @note use only for functions where there is only "netif" parameter.
*/
err_t
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
netifapi_errt_fn errtfunc)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
NETIFAPI_VAR_REF(msg).netif = netif;
NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
/**
* @ingroup netifapi_netif
* Call netif_name_to_index() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @param name the interface name of the netif
* @param idx output index of the found netif
*/
err_t
netifapi_netif_name_to_index(const char *name, u8_t *idx)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
*idx = 0;
#if LWIP_MPU_COMPATIBLE
strncpy(NETIFAPI_VAR_REF(msg).msg.ifs.name, name, NETIF_NAMESIZE - 1);
NETIFAPI_VAR_REF(msg).msg.ifs.name[NETIF_NAMESIZE - 1] = '\0';
#else
NETIFAPI_VAR_REF(msg).msg.ifs.name = LWIP_CONST_CAST(char *, name);
#endif /* LWIP_MPU_COMPATIBLE */
err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call);
if (!err) {
*idx = NETIFAPI_VAR_REF(msg).msg.ifs.index;
}
NETIFAPI_VAR_FREE(msg);
return err;
}
/**
* @ingroup netifapi_netif
* Call netif_index_to_name() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @param idx the interface index of the netif
* @param name output name of the found netif, empty '\0' string if netif not found.
* name should be of at least NETIF_NAMESIZE bytes
*/
err_t
netifapi_netif_index_to_name(u8_t idx, char *name)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
NETIFAPI_VAR_REF(msg).msg.ifs.index = idx;
#if !LWIP_MPU_COMPATIBLE
NETIFAPI_VAR_REF(msg).msg.ifs.name = name;
#endif /* LWIP_MPU_COMPATIBLE */
err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call);
#if LWIP_MPU_COMPATIBLE
if (!err) {
strncpy(name, NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE - 1);
name[NETIF_NAMESIZE - 1] = '\0';
}
#endif /* LWIP_MPU_COMPATIBLE */
NETIFAPI_VAR_FREE(msg);
return err;
}
#endif /* LWIP_NETIF_API */

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,8 @@
/**
* @file
* Sequential API Main thread module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -17,642 +11,127 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/opt.h"
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
#include "lwip/priv/tcpip_priv.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
#include "lwip/init.h"
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
/* global variables */
static tcpip_init_done_fn tcpip_init_done;
#include "lwip/tcpip.h"
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
static sys_mbox_t tcpip_mbox;
static sys_mbox_t mbox;
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */
static void tcpip_thread_handle_msg(struct tcpip_msg *msg);
#if !LWIP_TIMERS
/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
#else /* !LWIP_TIMERS */
/* wait for a message, timeouts are processed while waiting */
#define TCPIP_MBOX_FETCH(mbox, msg) tcpip_timeouts_mbox_fetch(mbox, msg)
/**
* Wait (forever) for a message to arrive in an mbox.
* While waiting, timeouts are processed.
*
* @param mbox the mbox to fetch the message from
* @param msg the place to store the message
*/
/*-----------------------------------------------------------------------------------*/
static void
tcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
tcpip_tcp_timer(void *arg)
{
u32_t sleeptime, res;
again:
LWIP_ASSERT_CORE_LOCKED();
sleeptime = sys_timeouts_sleeptime();
if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {
UNLOCK_TCPIP_CORE();
sys_arch_mbox_fetch(mbox, msg, 0);
LOCK_TCPIP_CORE();
return;
} else if (sleeptime == 0) {
sys_check_timeouts();
/* We try again to fetch a message from the mbox. */
goto again;
}
UNLOCK_TCPIP_CORE();
res = sys_arch_mbox_fetch(mbox, msg, sleeptime);
LOCK_TCPIP_CORE();
if (res == SYS_ARCH_TIMEOUT) {
/* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
before a message could be fetched. */
sys_check_timeouts();
/* We try again to fetch a message from the mbox. */
goto again;
}
tcp_tmr();
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
}
#endif /* !LWIP_TIMERS */
/*-----------------------------------------------------------------------------------*/
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
* (unless access to them is not locked). Other threads communicate with this
* thread using message boxes.
*
* It also starts all the timers to make sure they are running in the right
* thread context.
*
* @param arg unused argument
*/
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
LWIP_UNUSED_ARG(arg);
LWIP_MARK_TCPIP_THREAD();
ip_init();
udp_init();
tcp_init();
LOCK_TCPIP_CORE();
if (tcpip_init_done != NULL) {
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
if(tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
while (1) { /* MAIN Loop */
LWIP_TCPIP_THREAD_ALIVE();
/* wait for a message, timeouts are processed while waiting */
TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
if (msg == NULL) {
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
continue;
}
tcpip_thread_handle_msg(msg);
}
}
/* Handle a single tcpip_msg
* This is in its own function for access by tests only.
*/
static void
tcpip_thread_handle_msg(struct tcpip_msg *msg)
{
switch (msg->type) {
#if !LWIP_TCPIP_CORE_LOCKING
while(1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg);
switch(msg->type) {
case TCPIP_MSG_API:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
msg->msg.api_msg.function(msg->msg.api_msg.msg);
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", msg));
api_msg_input(msg->msg.apimsg);
break;
case TCPIP_MSG_API_CALL:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
sys_sem_signal(msg->msg.api_call.sem);
case TCPIP_MSG_INPUT:
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", msg));
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING */
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
case TCPIP_MSG_INPKT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
if (msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif) != ERR_OK) {
pbuf_free(msg->msg.inp.p);
}
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
case TCPIP_MSG_TIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_UNTIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_CALLBACK_STATIC:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
break;
default:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
break;
}
}
#ifdef TCPIP_THREAD_TEST
/** Work on queued items in single-threaded test mode */
int
tcpip_thread_poll_one(void)
{
int ret = 0;
struct tcpip_msg *msg;
if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_MBOX_EMPTY) {
LOCK_TCPIP_CORE();
if (msg != NULL) {
tcpip_thread_handle_msg(msg);
ret = 1;
}
UNLOCK_TCPIP_CORE();
memp_freep(MEMP_TCPIP_MSG, msg);
}
return ret;
}
#endif
/**
* Pass a received packet to tcpip_thread for input processing
*
* @param p the received packet
* @param inp the network interface on which the packet was received
* @param input_fn input function to call
*/
err_t
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
{
#if LWIP_TCPIP_CORE_LOCKING_INPUT
err_t ret;
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
LOCK_TCPIP_CORE();
ret = input_fn(p, inp);
UNLOCK_TCPIP_CORE();
return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPKT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
msg->msg.inp.input_fn = input_fn;
if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
/**
* @ingroup lwip_os
* Pass a received packet to tcpip_thread for input processing with
* ethernet_input or ip_input. Don't call directly, pass to netif_add()
* and call netif->input().
*
* @param p the received packet, p->payload pointing to the Ethernet header or
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
* NETIF_FLAG_ETHERNET flags)
* @param inp the network interface on which the packet was received
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_ETHERNET
if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
return tcpip_inpkt(p, inp, ethernet_input);
} else
#endif /* LWIP_ETHERNET */
return tcpip_inpkt(p, inp, ip_input);
}
/**
* @ingroup lwip_os
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
* Blocks until the request is posted.
* Must not be called from interrupt context!
*
* @param function the function to call
* @param ctx parameter passed to f
* @return ERR_OK if the function was called, another err_t if not
*
* @see tcpip_try_callback
*/
err_t
tcpip_callback(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
pbuf_free(p);
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
sys_mbox_post(&tcpip_mbox, msg);
msg->type = TCPIP_MSG_INPUT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/**
* @ingroup lwip_os
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
* Does NOT block when the request cannot be posted because the
* tcpip_mbox is full, but returns ERR_MEM instead.
* Can be called from interrupt context.
*
* @param function the function to call
* @param ctx parameter passed to f
* @return ERR_OK if the function was called, another err_t if not
*
* @see tcpip_callback
*/
err_t
tcpip_try_callback(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
return ERR_OK;
}
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
/**
* call sys_timeout in tcpip_thread
*
* @param msecs time in milliseconds for timeout
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_TIMEOUT;
msg->msg.tmo.msecs = msecs;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&tcpip_mbox, msg);
return ERR_OK;
}
/**
* call sys_untimeout in tcpip_thread
*
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_untimeout(sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_UNTIMEOUT;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&tcpip_mbox, msg);
return ERR_OK;
}
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
/**
* Sends a message to TCPIP thread to call a function. Caller thread blocks on
* on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
* this has to be done by the user.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
* with least runtime overhead.
*
* @param fn function to be called from TCPIP thread
* @param apimsg argument to API function
* @param sem semaphore to wait on
* @return ERR_OK if the function was called, another err_t if not
*/
err_t
tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
{
#if LWIP_TCPIP_CORE_LOCKING
LWIP_UNUSED_ARG(sem);
LOCK_TCPIP_CORE();
fn(apimsg);
UNLOCK_TCPIP_CORE();
return ERR_OK;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(sem, 0);
TCPIP_MSG_VAR_FREE(msg);
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* Synchronously calls function in TCPIP thread and waits for its completion.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
* LWIP_NETCONN_SEM_PER_THREAD.
* If not, a semaphore is created and destroyed on every call which is usually
* an expensive/slow operation.
* @param fn Function to call
* @param call Call parameters
* @return Return value from tcpip_api_call_fn
*/
err_t
tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
{
#if LWIP_TCPIP_CORE_LOCKING
err_t err;
LOCK_TCPIP_CORE();
err = fn(call);
UNLOCK_TCPIP_CORE();
return err;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
err_t err = sys_sem_new(&call->sem, 0);
if (err != ERR_OK) {
return err;
}
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
#if LWIP_NETCONN_SEM_PER_THREAD
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
#else /* LWIP_NETCONN_SEM_PER_THREAD */
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
TCPIP_MSG_VAR_FREE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(&call->sem);
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
return call->err;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* @ingroup lwip_os
* Allocate a structure for a static callback message and initialize it.
* The message has a special type such that lwIP never frees it.
* This is intended to be used to send "static" messages from interrupt context,
* e.g. the message is allocated once and posted several times from an IRQ
* using tcpip_callbackmsg_trycallback().
* Example usage: Trigger execution of an ethernet IRQ DPC routine in lwIP thread context.
*
* @param function the function to call
* @param ctx parameter passed to function
* @return a struct pointer to pass to tcpip_callbackmsg_trycallback().
*
* @see tcpip_callbackmsg_trycallback()
* @see tcpip_callbackmsg_delete()
*/
struct tcpip_callback_msg *
tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return NULL;
}
msg->type = TCPIP_MSG_CALLBACK_STATIC;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
return (struct tcpip_callback_msg *)msg;
}
/**
* @ingroup lwip_os
* Free a callback message allocated by tcpip_callbackmsg_new().
*
* @param msg the message to free
*
* @see tcpip_callbackmsg_new()
*/
/*-----------------------------------------------------------------------------------*/
void
tcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
tcpip_apimsg(struct api_msg *apimsg)
{
memp_free(MEMP_TCPIP_MSG_API, msg);
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
}
msg->type = TCPIP_MSG_API;
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/**
* @ingroup lwip_os
* Try to post a callback-message to the tcpip_thread tcpip_mbox.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost() return code
*
* @see tcpip_callbackmsg_new()
*/
err_t
tcpip_callbackmsg_trycallback(struct tcpip_callback_msg *msg)
{
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
return sys_mbox_trypost(&tcpip_mbox, msg);
}
/**
* @ingroup lwip_os
* Try to post a callback-message to the tcpip_thread mbox.
* Same as @ref tcpip_callbackmsg_trycallback but calls sys_mbox_trypost_fromisr(),
* mainly to help FreeRTOS, where calls differ between task level and ISR level.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost_fromisr() return code (without change, so this
* knowledge can be used to e.g. propagate "bool needs_scheduling")
*
* @see tcpip_callbackmsg_new()
*/
err_t
tcpip_callbackmsg_trycallback_fromisr(struct tcpip_callback_msg *msg)
{
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
return sys_mbox_trypost_fromisr(&tcpip_mbox, msg);
}
/**
* @ingroup lwip_os
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
tcpip_init(void (* initfunc)(void *), void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
mbox = sys_mbox_new();
sys_thread_new((void *)tcpip_thread, NULL);
}
/*-----------------------------------------------------------------------------------*/
/**
* Simple callback function used with tcpip_callback to free a pbuf
* (pbuf_free has a wrong signature for tcpip_callback)
*
* @param p The pbuf (chain) to be dereferenced.
*/
static void
pbuf_free_int(void *p)
{
struct pbuf *q = (struct pbuf *)p;
pbuf_free(q);
}
/**
* A simple wrapper function that allows you to free a pbuf from interrupt context.
*
* @param p The pbuf (chain) to be dereferenced.
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
pbuf_free_callback(struct pbuf *p)
{
return tcpip_try_callback(pbuf_free_int, p);
}
/**
* A simple wrapper function that allows you to free heap memory from
* interrupt context.
*
* @param m the heap memory to free
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
mem_free_callback(void *m)
{
return tcpip_try_callback(mem_free, m);
}
#endif /* !NO_SYS */

File diff suppressed because it is too large Load Diff

View File

@@ -1,210 +0,0 @@
/**
* @file
* Application layered TCP connection API (to be used from TCPIP thread)
*
* This file contains memory management functions for a TLS layer using mbedTLS.
*
* ATTENTION: For production usage, you might want to override this file with
* your own implementation since this implementation simply uses the
* lwIP heap without caring for fragmentation or leaving heap for
* other parts of lwIP!
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
* Missing things / @todo:
* - RX data is acknowledged after receiving (tcp_recved is called when enqueueing
* the pbuf for mbedTLS receive, not when processed by mbedTLS or the inner
* connection; altcp_recved() from inner connection does nothing)
* - TX data is marked as 'sent' (i.e. acknowledged; sent callback is called) right
* after enqueueing for transmission, not when actually ACKed be the remote host.
*/
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/altcp_tls_mbedtls_opts.h"
#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS
#include "altcp_tls_mbedtls_mem.h"
#include "altcp_tls_mbedtls_structs.h"
#include "lwip/mem.h"
#include "mbedtls/platform.h"
#include <string.h>
#ifndef ALTCP_MBEDTLS_MEM_DEBUG
#define ALTCP_MBEDTLS_MEM_DEBUG LWIP_DBG_OFF
#endif
#if defined(MBEDTLS_PLATFORM_MEMORY) && \
(!defined(MBEDTLS_PLATFORM_FREE_MACRO) || \
defined(MBEDTLS_PLATFORM_CALLOC_MACRO))
#define ALTCP_MBEDTLS_PLATFORM_ALLOC 1
#else
#define ALTCP_MBEDTLS_PLATFORM_ALLOC 0
#endif
#if ALTCP_MBEDTLS_PLATFORM_ALLOC
#ifndef ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
#define ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS 0
#endif
/* This is an example/debug implementation of alloc/free functions only */
typedef struct altcp_mbedtls_malloc_helper_s {
size_t c;
size_t len;
} altcp_mbedtls_malloc_helper_t;
#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
typedef struct altcp_mbedtls_malloc_stats_s {
size_t allocedBytes;
size_t allocCnt;
size_t maxBytes;
size_t totalBytes;
} altcp_mbedtls_malloc_stats_t;
altcp_mbedtls_malloc_stats_t altcp_mbedtls_malloc_stats;
volatile int altcp_mbedtls_malloc_clear_stats;
#endif
static void *
tls_malloc(size_t c, size_t len)
{
altcp_mbedtls_malloc_helper_t *hlpr;
void *ret;
size_t alloc_size;
#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
if (altcp_mbedtls_malloc_clear_stats) {
altcp_mbedtls_malloc_clear_stats = 0;
memset(&altcp_mbedtls_malloc_stats, 0, sizeof(altcp_mbedtls_malloc_stats));
}
#endif
alloc_size = sizeof(altcp_mbedtls_malloc_helper_t) + (c * len);
/* check for maximum allocation size, mainly to prevent mem_size_t overflow */
if (alloc_size > MEM_SIZE) {
LWIP_DEBUGF(ALTCP_MBEDTLS_MEM_DEBUG, ("mbedtls allocation too big: %c * %d bytes vs MEM_SIZE=%d",
(int)c, (int)len, (int)MEM_SIZE));
return NULL;
}
hlpr = (altcp_mbedtls_malloc_helper_t *)mem_malloc((mem_size_t)alloc_size);
if (hlpr == NULL) {
LWIP_DEBUGF(ALTCP_MBEDTLS_MEM_DEBUG, ("mbedtls alloc callback failed for %c * %d bytes", (int)c, (int)len));
return NULL;
}
#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
altcp_mbedtls_malloc_stats.allocCnt++;
altcp_mbedtls_malloc_stats.allocedBytes += c * len;
if (altcp_mbedtls_malloc_stats.allocedBytes > altcp_mbedtls_malloc_stats.maxBytes) {
altcp_mbedtls_malloc_stats.maxBytes = altcp_mbedtls_malloc_stats.allocedBytes;
}
altcp_mbedtls_malloc_stats.totalBytes += c * len;
#endif
hlpr->c = c;
hlpr->len = len;
ret = hlpr + 1;
/* zeroing the allocated chunk is required by mbedTLS! */
memset(ret, 0, c * len);
return ret;
}
static void
tls_free(void *ptr)
{
altcp_mbedtls_malloc_helper_t *hlpr;
if (ptr == NULL) {
/* this obviously happened in mbedtls... */
return;
}
hlpr = ((altcp_mbedtls_malloc_helper_t *)ptr) - 1;
#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
if (!altcp_mbedtls_malloc_clear_stats) {
altcp_mbedtls_malloc_stats.allocedBytes -= hlpr->c * hlpr->len;
}
#endif
mem_free(hlpr);
}
#endif /* ALTCP_MBEDTLS_PLATFORM_ALLOC*/
void
altcp_mbedtls_mem_init(void)
{
/* not much to do here when using the heap */
#if ALTCP_MBEDTLS_PLATFORM_ALLOC
/* set mbedtls allocation methods */
mbedtls_platform_set_calloc_free(&tls_malloc, &tls_free);
#endif
}
altcp_mbedtls_state_t *
altcp_mbedtls_alloc(void *conf)
{
altcp_mbedtls_state_t *ret = (altcp_mbedtls_state_t *)mem_calloc(1, sizeof(altcp_mbedtls_state_t));
if (ret != NULL) {
ret->conf = conf;
}
return ret;
}
void
altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state)
{
LWIP_UNUSED_ARG(conf);
LWIP_ASSERT("state != NULL", state != NULL);
mem_free(state);
}
void *
altcp_mbedtls_alloc_config(size_t size)
{
void *ret;
size_t checked_size = (mem_size_t)size;
if (size != checked_size) {
/* allocation too big (mem_size_t overflow) */
return NULL;
}
ret = (altcp_mbedtls_state_t *)mem_calloc(1, (mem_size_t)size);
return ret;
}
void
altcp_mbedtls_free_config(void *item)
{
LWIP_ASSERT("item != NULL", item != NULL);
mem_free(item);
}
#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
#endif /* LWIP_ALTCP */

View File

@@ -1,72 +0,0 @@
/**
* @file
* Application layered TCP/TLS connection API (to be used from TCPIP thread)
*
* This file contains memory management function prototypes for a TLS layer using mbedTLS.
*
* Memory management contains:
* - allocating/freeing altcp_mbedtls_state_t
* - allocating/freeing memory used in the mbedTLS library
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_MBEDTLS_MEM_H
#define LWIP_HDR_ALTCP_MBEDTLS_MEM_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/altcp_tls_mbedtls_opts.h"
#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS
#include "altcp_tls_mbedtls_structs.h"
#ifdef __cplusplus
extern "C" {
#endif
void altcp_mbedtls_mem_init(void);
altcp_mbedtls_state_t *altcp_mbedtls_alloc(void *conf);
void altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state);
void *altcp_mbedtls_alloc_config(size_t size);
void altcp_mbedtls_free_config(void *item);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_MBEDTLS_MEM_H */

View File

@@ -1,83 +0,0 @@
/**
* @file
* Application layered TCP/TLS connection API (to be used from TCPIP thread)
*
* This file contains structure definitions for a TLS layer using mbedTLS.
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H
#define LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/altcp_tls_mbedtls_opts.h"
#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS
#include "lwip/altcp.h"
#include "lwip/pbuf.h"
#include "mbedtls/ssl.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE 0x01
#define ALTCP_MBEDTLS_FLAGS_UPPER_CALLED 0x02
#define ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED 0x04
#define ALTCP_MBEDTLS_FLAGS_RX_CLOSED 0x08
#define ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT 0x10
typedef struct altcp_mbedtls_state_s {
void *conf;
mbedtls_ssl_context ssl_context;
/* chain of rx pbufs (before decryption) */
struct pbuf *rx;
struct pbuf *rx_app;
u8_t flags;
int rx_passed_unrecved;
int bio_bytes_read;
int bio_bytes_appl;
} altcp_mbedtls_state_t;
#ifdef __cplusplus
}
#endif
#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H */

View File

@@ -1,584 +0,0 @@
/**
* @file
* Application layered TCP connection API that executes a proxy-connect.
*
* This file provides a starting layer that executes a proxy-connect e.g. to
* set up TLS connections through a http proxy.
*/
/*
* Copyright (c) 2018 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#include "lwip/apps/altcp_proxyconnect.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/altcp.h"
#include "lwip/priv/altcp_priv.h"
#include "lwip/altcp_tcp.h"
#include "lwip/altcp_tls.h"
#include "lwip/mem.h"
#include "lwip/init.h"
#include <stdio.h>
/** This string is passed in the HTTP header as "User-Agent: " */
#ifndef ALTCP_PROXYCONNECT_CLIENT_AGENT
#define ALTCP_PROXYCONNECT_CLIENT_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)"
#endif
#define ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED 0x01
#define ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE 0x02
typedef struct altcp_proxyconnect_state_s
{
ip_addr_t outer_addr;
u16_t outer_port;
struct altcp_proxyconnect_config *conf;
u8_t flags;
} altcp_proxyconnect_state_t;
/* Variable prototype, the actual declaration is at the end of this file
since it contains pointers to static functions declared here */
extern const struct altcp_functions altcp_proxyconnect_functions;
/* memory management functions: */
static altcp_proxyconnect_state_t *
altcp_proxyconnect_state_alloc(void)
{
altcp_proxyconnect_state_t *ret = (altcp_proxyconnect_state_t *)mem_calloc(1, sizeof(altcp_proxyconnect_state_t));
return ret;
}
static void
altcp_proxyconnect_state_free(altcp_proxyconnect_state_t *state)
{
LWIP_ASSERT("state != NULL", state != NULL);
mem_free(state);
}
/* helper functions */
#define PROXY_CONNECT "CONNECT %s:%d HTTP/1.1\r\n" /* HOST, PORT */ \
"User-Agent: %s\r\n" /* User-Agent */\
"Proxy-Connection: keep-alive\r\n" \
"Connection: keep-alive\r\n" \
"\r\n"
#define PROXY_CONNECT_FORMAT(host, port) PROXY_CONNECT, host, port, ALTCP_PROXYCONNECT_CLIENT_AGENT
/* Format the http proxy connect request via snprintf */
static int
altcp_proxyconnect_format_request(char *buffer, size_t bufsize, const char *host, int port)
{
return snprintf(buffer, bufsize, PROXY_CONNECT_FORMAT(host, port));
}
/* Create and send the http proxy connect request */
static err_t
altcp_proxyconnect_send_request(struct altcp_pcb *conn)
{
int len, len2;
mem_size_t alloc_len;
char *buffer, *host;
altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state;
if (!state) {
return ERR_VAL;
}
/* Use printf with zero length to get the required allocation size */
len = altcp_proxyconnect_format_request(NULL, 0, "", state->outer_port);
if (len < 0) {
return ERR_VAL;
}
/* add allocation size for IP address strings */
#if LWIP_IPV6
len += 40; /* worst-case IPv6 address length */
#else
len += 16; /* worst-case IPv4 address length */
#endif
alloc_len = (mem_size_t)len;
if ((len < 0) || (int)alloc_len != len) {
/* overflow */
return ERR_MEM;
}
/* Allocate a bufer for the request string */
buffer = (char *)mem_malloc(alloc_len);
if (buffer == NULL) {
return ERR_MEM;
}
host = ipaddr_ntoa(&state->outer_addr);
len2 = altcp_proxyconnect_format_request(buffer, alloc_len, host, state->outer_port);
if ((len2 > 0) && (len2 <= len) && (len2 <= 0xFFFF)) {
err_t err = altcp_write(conn->inner_conn, buffer, (u16_t)len2, TCP_WRITE_FLAG_COPY);
if (err != ERR_OK) {
/* @todo: abort? */
mem_free(buffer);
return err;
}
}
mem_free(buffer);
return ERR_OK;
}
/* callback functions from inner/lower connection: */
/** Connected callback from lower connection (i.e. TCP).
* Not really implemented/tested yet...
*/
static err_t
altcp_proxyconnect_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err)
{
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
if (conn && conn->state) {
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
/* upper connected is called when handshake is done */
if (err != ERR_OK) {
if (conn->connected) {
if (conn->connected(conn->arg, conn, err) == ERR_ABRT) {
return ERR_ABRT;
}
return ERR_OK;
}
}
/* send proxy connect request here */
return altcp_proxyconnect_send_request(conn);
}
return ERR_VAL;
}
/** Recv callback from lower connection (i.e. TCP)
* This one mainly differs between connection setup (wait for proxy OK string)
* and application phase (data is passed on to the application).
*/
static err_t
altcp_proxyconnect_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err)
{
altcp_proxyconnect_state_t *state;
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
LWIP_ASSERT("no err expected", err == ERR_OK);
LWIP_UNUSED_ARG(err);
if (!conn) {
/* no connection given as arg? should not happen, but prevent pbuf/conn leaks */
if (p != NULL) {
pbuf_free(p);
}
altcp_close(inner_conn);
return ERR_CLSD;
}
state = (altcp_proxyconnect_state_t *)conn->state;
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
if (!state) {
/* already closed */
if (p != NULL) {
pbuf_free(p);
}
altcp_close(inner_conn);
return ERR_CLSD;
}
if (state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE) {
/* application phase, just pass this through */
if (conn->recv) {
return conn->recv(conn->arg, conn, p, err);
}
pbuf_free(p);
return ERR_OK;
} else {
/* setup phase */
/* handle NULL pbuf (inner connection closed) */
if (p == NULL) {
if (altcp_close(conn) != ERR_OK) {
altcp_abort(conn);
return ERR_ABRT;
}
return ERR_OK;
} else {
/* @todo: parse setup phase rx data
for now, we just wait for the end of the header... */
u16_t idx = pbuf_memfind(p, "\r\n\r\n", 4, 0);
altcp_recved(inner_conn, p->tot_len);
pbuf_free(p);
if (idx != 0xFFFF) {
state->flags |= ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE;
if (conn->connected) {
return conn->connected(conn->arg, conn, ERR_OK);
}
}
return ERR_OK;
}
}
}
/** Sent callback from lower connection (i.e. TCP)
* This only informs the upper layer to try to send more, not about
* the number of ACKed bytes.
*/
static err_t
altcp_proxyconnect_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
{
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
LWIP_UNUSED_ARG(len);
if (conn) {
altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state;
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
if (!state || !(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) {
/* @todo: do something here? */
return ERR_OK;
}
/* pass this on to upper sent */
if (conn->sent) {
return conn->sent(conn->arg, conn, len);
}
}
return ERR_OK;
}
/** Poll callback from lower connection (i.e. TCP)
* Just pass this on to the application.
* @todo: retry sending?
*/
static err_t
altcp_proxyconnect_lower_poll(void *arg, struct altcp_pcb *inner_conn)
{
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
if (conn) {
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
if (conn->poll) {
return conn->poll(conn->arg, conn);
}
}
return ERR_OK;
}
static void
altcp_proxyconnect_lower_err(void *arg, err_t err)
{
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
if (conn) {
conn->inner_conn = NULL; /* already freed */
if (conn->err) {
conn->err(conn->arg, err);
}
altcp_free(conn);
}
}
/* setup functions */
static void
altcp_proxyconnect_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
{
altcp_arg(inner_conn, conn);
altcp_recv(inner_conn, altcp_proxyconnect_lower_recv);
altcp_sent(inner_conn, altcp_proxyconnect_lower_sent);
altcp_err(inner_conn, altcp_proxyconnect_lower_err);
/* tcp_poll is set when interval is set by application */
/* listen is set totally different :-) */
}
static err_t
altcp_proxyconnect_setup(struct altcp_proxyconnect_config *config, struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
{
altcp_proxyconnect_state_t *state;
if (!config) {
return ERR_ARG;
}
LWIP_ASSERT("invalid inner_conn", conn != inner_conn);
/* allocate proxyconnect context */
state = altcp_proxyconnect_state_alloc();
if (state == NULL) {
return ERR_MEM;
}
state->flags = 0;
state->conf = config;
altcp_proxyconnect_setup_callbacks(conn, inner_conn);
conn->inner_conn = inner_conn;
conn->fns = &altcp_proxyconnect_functions;
conn->state = state;
return ERR_OK;
}
/** Allocate a new altcp layer connecting through a proxy.
* This function gets the inner pcb passed.
*
* @param config struct altcp_proxyconnect_config that contains the proxy settings
* @param inner_pcb pcb that makes the connection to the proxy (i.e. tcp pcb)
*/
struct altcp_pcb *
altcp_proxyconnect_new(struct altcp_proxyconnect_config *config, struct altcp_pcb *inner_pcb)
{
struct altcp_pcb *ret;
if (inner_pcb == NULL) {
return NULL;
}
ret = altcp_alloc();
if (ret != NULL) {
if (altcp_proxyconnect_setup(config, ret, inner_pcb) != ERR_OK) {
altcp_free(ret);
return NULL;
}
}
return ret;
}
/** Allocate a new altcp layer connecting through a proxy.
* This function allocates the inner pcb as tcp pcb, resulting in a direct tcp
* connection to the proxy.
*
* @param config struct altcp_proxyconnect_config that contains the proxy settings
* @param ip_type IP type of the connection (@ref lwip_ip_addr_type)
*/
struct altcp_pcb *
altcp_proxyconnect_new_tcp(struct altcp_proxyconnect_config *config, u8_t ip_type)
{
struct altcp_pcb *inner_pcb, *ret;
/* inner pcb is tcp */
inner_pcb = altcp_tcp_new_ip_type(ip_type);
if (inner_pcb == NULL) {
return NULL;
}
ret = altcp_proxyconnect_new(config, inner_pcb);
if (ret == NULL) {
altcp_close(inner_pcb);
}
return ret;
}
/** Allocator function to allocate a proxy connect altcp pcb connecting directly
* via tcp to the proxy.
*
* The returned pcb is a chain: altcp_proxyconnect - altcp_tcp - tcp pcb
*
* This function is meant for use with @ref altcp_new.
*
* @param arg struct altcp_proxyconnect_config that contains the proxy settings
* @param ip_type IP type of the connection (@ref lwip_ip_addr_type)
*/
struct altcp_pcb *
altcp_proxyconnect_alloc(void *arg, u8_t ip_type)
{
return altcp_proxyconnect_new_tcp((struct altcp_proxyconnect_config *)arg, ip_type);
}
#if LWIP_ALTCP_TLS
/** Allocator function to allocate a TLS connection through a proxy.
*
* The returned pcb is a chain: altcp_tls - altcp_proxyconnect - altcp_tcp - tcp pcb
*
* This function is meant for use with @ref altcp_new.
*
* @param arg struct altcp_proxyconnect_tls_config that contains the proxy settings
* and tls settings
* @param ip_type IP type of the connection (@ref lwip_ip_addr_type)
*/
struct altcp_pcb *
altcp_proxyconnect_tls_alloc(void *arg, u8_t ip_type)
{
struct altcp_proxyconnect_tls_config *cfg = (struct altcp_proxyconnect_tls_config *)arg;
struct altcp_pcb *proxy_pcb;
struct altcp_pcb *tls_pcb;
proxy_pcb = altcp_proxyconnect_new_tcp(&cfg->proxy, ip_type);
tls_pcb = altcp_tls_wrap(cfg->tls_config, proxy_pcb);
if (tls_pcb == NULL) {
altcp_close(proxy_pcb);
}
return tls_pcb;
}
#endif /* LWIP_ALTCP_TLS */
/* "virtual" functions */
static void
altcp_proxyconnect_set_poll(struct altcp_pcb *conn, u8_t interval)
{
if (conn != NULL) {
altcp_poll(conn->inner_conn, altcp_proxyconnect_lower_poll, interval);
}
}
static void
altcp_proxyconnect_recved(struct altcp_pcb *conn, u16_t len)
{
altcp_proxyconnect_state_t *state;
if (conn == NULL) {
return;
}
state = (altcp_proxyconnect_state_t *)conn->state;
if (state == NULL) {
return;
}
if (!(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) {
return;
}
altcp_recved(conn->inner_conn, len);
}
static err_t
altcp_proxyconnect_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
{
altcp_proxyconnect_state_t *state;
if ((conn == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
state = (altcp_proxyconnect_state_t *)conn->state;
if (state == NULL) {
return ERR_VAL;
}
if (state->flags & ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED) {
return ERR_VAL;
}
state->flags |= ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED;
conn->connected = connected;
/* connect to our proxy instead, but store the requested address and port */
ip_addr_copy(state->outer_addr, *ipaddr);
state->outer_port = port;
return altcp_connect(conn->inner_conn, &state->conf->proxy_addr, state->conf->proxy_port, altcp_proxyconnect_lower_connected);
}
static struct altcp_pcb *
altcp_proxyconnect_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
{
LWIP_UNUSED_ARG(conn);
LWIP_UNUSED_ARG(backlog);
LWIP_UNUSED_ARG(err);
/* listen not supported! */
return NULL;
}
static void
altcp_proxyconnect_abort(struct altcp_pcb *conn)
{
if (conn != NULL) {
if (conn->inner_conn != NULL) {
altcp_abort(conn->inner_conn);
}
altcp_free(conn);
}
}
static err_t
altcp_proxyconnect_close(struct altcp_pcb *conn)
{
if (conn == NULL) {
return ERR_VAL;
}
if (conn->inner_conn != NULL) {
err_t err = altcp_close(conn->inner_conn);
if (err != ERR_OK) {
/* closing inner conn failed, return the error */
return err;
}
}
/* no inner conn or closing it succeeded, deallocate myself */
altcp_free(conn);
return ERR_OK;
}
static err_t
altcp_proxyconnect_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
{
altcp_proxyconnect_state_t *state;
LWIP_UNUSED_ARG(apiflags);
if (conn == NULL) {
return ERR_VAL;
}
state = (altcp_proxyconnect_state_t *)conn->state;
if (state == NULL) {
/* @todo: which error? */
return ERR_CLSD;
}
if (!(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) {
/* @todo: which error? */
return ERR_VAL;
}
return altcp_write(conn->inner_conn, dataptr, len, apiflags);
}
static void
altcp_proxyconnect_dealloc(struct altcp_pcb *conn)
{
/* clean up and free tls state */
if (conn) {
altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state;
if (state) {
altcp_proxyconnect_state_free(state);
conn->state = NULL;
}
}
}
const struct altcp_functions altcp_proxyconnect_functions = {
altcp_proxyconnect_set_poll,
altcp_proxyconnect_recved,
altcp_default_bind,
altcp_proxyconnect_connect,
altcp_proxyconnect_listen,
altcp_proxyconnect_abort,
altcp_proxyconnect_close,
altcp_default_shutdown,
altcp_proxyconnect_write,
altcp_default_output,
altcp_default_mss,
altcp_default_sndbuf,
altcp_default_sndqueuelen,
altcp_default_nagle_disable,
altcp_default_nagle_enable,
altcp_default_nagle_disabled,
altcp_default_setprio,
altcp_proxyconnect_dealloc,
altcp_default_get_tcp_addrinfo,
altcp_default_get_ip,
altcp_default_get_port
#ifdef LWIP_DEBUG
, altcp_default_dbg_get_tcp_state
#endif
};
#endif /* LWIP_ALTCP */

View File

@@ -1,174 +0,0 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/apps/httpd_opts.h"
#include "lwip/def.h"
#include "lwip/apps/fs.h"
#include <string.h>
#include HTTPD_FSDATA_FILE
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_CUSTOM_FILES
int fs_open_custom(struct fs_file *file, const char *name);
void fs_close_custom(struct fs_file *file);
#if LWIP_HTTPD_FS_ASYNC_READ
u8_t fs_canread_custom(struct fs_file *file);
u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_read_custom(struct fs_file *file, char *buffer, int count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#endif /* LWIP_HTTPD_CUSTOM_FILES */
/*-----------------------------------------------------------------------------------*/
err_t
fs_open(struct fs_file *file, const char *name)
{
const struct fsdata_file *f;
if ((file == NULL) || (name == NULL)) {
return ERR_ARG;
}
#if LWIP_HTTPD_CUSTOM_FILES
if (fs_open_custom(file, name)) {
file->is_custom_file = 1;
return ERR_OK;
}
file->is_custom_file = 0;
#endif /* LWIP_HTTPD_CUSTOM_FILES */
for (f = FS_ROOT; f != NULL; f = f->next) {
if (!strcmp(name, (const char *)f->name)) {
file->data = (const char *)f->data;
file->len = f->len;
file->index = f->len;
file->pextension = NULL;
file->flags = f->flags;
#if HTTPD_PRECALCULATED_CHECKSUM
file->chksum_count = f->chksum_count;
file->chksum = f->chksum;
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
#if LWIP_HTTPD_FILE_STATE
file->state = fs_state_init(file, name);
#endif /* #if LWIP_HTTPD_FILE_STATE */
return ERR_OK;
}
}
/* file not found */
return ERR_VAL;
}
/*-----------------------------------------------------------------------------------*/
void
fs_close(struct fs_file *file)
{
#if LWIP_HTTPD_CUSTOM_FILES
if (file->is_custom_file) {
fs_close_custom(file);
}
#endif /* LWIP_HTTPD_CUSTOM_FILES */
#if LWIP_HTTPD_FILE_STATE
fs_state_free(file, file->state);
#endif /* #if LWIP_HTTPD_FILE_STATE */
LWIP_UNUSED_ARG(file);
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_DYNAMIC_FILE_READ
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int
fs_read(struct fs_file *file, char *buffer, int count)
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
{
int read;
if (file->index == file->len) {
return FS_READ_EOF;
}
#if LWIP_HTTPD_FS_ASYNC_READ
LWIP_UNUSED_ARG(callback_fn);
LWIP_UNUSED_ARG(callback_arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#if LWIP_HTTPD_CUSTOM_FILES
if (file->is_custom_file) {
#if LWIP_HTTPD_FS_ASYNC_READ
return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
return fs_read_custom(file, buffer, count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
}
#endif /* LWIP_HTTPD_CUSTOM_FILES */
read = file->len - file->index;
if (read > count) {
read = count;
}
MEMCPY(buffer, (file->data + file->index), read);
file->index += read;
return (read);
}
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
{
if (file != NULL) {
#if LWIP_HTTPD_FS_ASYNC_READ
#if LWIP_HTTPD_CUSTOM_FILES
if (!fs_canread_custom(file)) {
if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
return 0;
}
}
#else /* LWIP_HTTPD_CUSTOM_FILES */
LWIP_UNUSED_ARG(callback_fn);
LWIP_UNUSED_ARG(callback_arg);
#endif /* LWIP_HTTPD_CUSTOM_FILES */
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
}
return 1;
}
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
/*-----------------------------------------------------------------------------------*/
int
fs_bytes_left(struct fs_file *file)
{
return file->len - file->index;
}

View File

@@ -1,21 +0,0 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
<body bgcolor="white" text="black">
<table width="100%">
<tr valign="top"><td width="80">
<a href="http://www.sics.se/"><img src="/img/sics.gif"
border="0" alt="SICS logo" title="SICS logo"></a>
</td><td width="500">
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
<h2>404 - Page not found</h2>
<p>
Sorry, the page you are requesting was not found on this
server.
</p>
</td><td>
&nbsp;
</td></tr>
</table>
</body>
</html>

View File

@@ -1,47 +0,0 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
<body bgcolor="white" text="black">
<table width="100%">
<tr valign="top"><td width="80">
<a href="http://www.sics.se/"><img src="/img/sics.gif"
border="0" alt="SICS logo" title="SICS logo"></a>
</td><td width="500">
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
<p>
The web page you are watching was served by a simple web
server running on top of the lightweight TCP/IP stack <a
href="http://www.sics.se/~adam/lwip/">lwIP</a>.
</p>
<p>
lwIP is an open source implementation of the TCP/IP
protocol suite that was originally written by <a
href="http://www.sics.se/~adam/lwip/">Adam Dunkels
of the Swedish Institute of Computer Science</a> but now is
being actively developed by a team of developers
distributed world-wide. Since it's release, lwIP has
spurred a lot of interest and has been ported to several
platforms and operating systems. lwIP can be used either
with or without an underlying OS.
</p>
<p>
The focus of the lwIP TCP/IP implementation is to reduce
the RAM usage while still having a full scale TCP. This
makes lwIP suitable for use in embedded systems with tens
of kilobytes of free RAM and room for around 40 kilobytes
of code ROM.
</p>
<p>
More information about lwIP can be found at the lwIP
homepage at <a
href="http://savannah.nongnu.org/projects/lwip/">http://savannah.nongnu.org/projects/lwip/</a>
or at the lwIP wiki at <a
href="http://lwip.wikia.com/">http://lwip.wikia.com/</a>.
</p>
</td><td>
&nbsp;
</td></tr>
</table>
</body>
</html>

View File

@@ -1,337 +0,0 @@
#include "lwip/apps/fs.h"
#include "lwip/def.h"
#define file_NULL (struct fsdata_file *) NULL
#ifndef FS_FILE_FLAGS_HEADER_INCLUDED
#define FS_FILE_FLAGS_HEADER_INCLUDED 1
#endif
#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT
#define FS_FILE_FLAGS_HEADER_PERSISTENT 0
#endif
/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */
#ifndef FSDATA_FILE_ALIGNMENT
#define FSDATA_FILE_ALIGNMENT 0
#endif
#ifndef FSDATA_ALIGN_PRE
#define FSDATA_ALIGN_PRE
#endif
#ifndef FSDATA_ALIGN_POST
#define FSDATA_ALIGN_POST
#endif
#if FSDATA_FILE_ALIGNMENT==2
#include "fsdata_alignment.h"
#endif
#if FSDATA_FILE_ALIGNMENT==1
static const unsigned int dummy_align__img_sics_gif = 0;
#endif
static const unsigned char FSDATA_ALIGN_PRE data__img_sics_gif[] FSDATA_ALIGN_POST = {
/* /img/sics.gif (14 chars) */
0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00,
/* HTTP header */
/* "HTTP/1.0 200 OK
" (17 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
0x0a,
/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip)
" (64 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30,
0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,
0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,
0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-Length: 724
" (18+ bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,
0x37,0x32,0x34,0x0d,0x0a,
/* "Content-Type: image/gif
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d,
0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a,
/* raw file data (724 bytes) */
0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39,
0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6,
0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e,
0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99,
0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5,
0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b,
0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00,
0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f,
0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac,
0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31,
0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9,
0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51,
0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78,
0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0,
0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07,
0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42,
0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c,
0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01,
0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10,
0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8,
0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4,
0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86,
0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06,
0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07,
0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29,
0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a,
0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97,
0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9,
0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70,
0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c,
0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01,
0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24,
0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29,
0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73,
0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab,
0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45,
0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8,
0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5,
0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10,
0x41,0x00,0x00,0x3b,};
#if FSDATA_FILE_ALIGNMENT==1
static const unsigned int dummy_align__404_html = 1;
#endif
static const unsigned char FSDATA_ALIGN_PRE data__404_html[] FSDATA_ALIGN_POST = {
/* /404.html (10 chars) */
0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00,
/* HTTP header */
/* "HTTP/1.0 404 File not found
" (29 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c,
0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a,
/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip)
" (64 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30,
0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,
0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,
0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-Length: 565
" (18+ bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,
0x35,0x36,0x35,0x0d,0x0a,
/* "Content-Type: text/html
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
/* raw file data (565 bytes) */
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20,
0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a,
0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72,
0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,
0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20,
0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e,
0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,
0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
0x6d,0x6c,0x3e,0x0d,0x0a,};
#if FSDATA_FILE_ALIGNMENT==1
static const unsigned int dummy_align__index_html = 2;
#endif
static const unsigned char FSDATA_ALIGN_PRE data__index_html[] FSDATA_ALIGN_POST = {
/* /index.html (12 chars) */
0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00,
/* HTTP header */
/* "HTTP/1.0 200 OK
" (17 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
0x0a,
/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip)
" (64 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30,
0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,
0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,
0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-Length: 1751
" (18+ bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,
0x31,0x37,0x35,0x31,0x0d,0x0a,
/* "Content-Type: text/html
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
/* raw file data (1751 bytes) */
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77,
0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20,
0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72,
0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20,
0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72,
0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20,
0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,
0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,
0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c,
0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,
0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,
0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20,
0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,
0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50,
0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63,
0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61,
0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69,
0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,
0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,
0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b,
0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,
0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75,
0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53,
0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e,
0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e,
0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c,
0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f,
0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20,
0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77,
0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65,
0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c,
0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70,
0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69,
0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20,
0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73,
0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61,
0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61,
0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77,
0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65,
0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,
0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75,
0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,
0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09,
0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67,
0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61,
0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c,
0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69,
0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e,
0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,
0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f,
0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72,
0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34,
0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a,
0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,
0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,
0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49,
0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61,
0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,
0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d,
0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,
0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,
0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,
0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,
0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f,
0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74,
0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61,
0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,
0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,
0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c,
0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,};
const struct fsdata_file file__img_sics_gif[] = { {
file_NULL,
data__img_sics_gif,
data__img_sics_gif + 16,
sizeof(data__img_sics_gif) - 16,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT,
}};
const struct fsdata_file file__404_html[] = { {
file__img_sics_gif,
data__404_html,
data__404_html + 12,
sizeof(data__404_html) - 12,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT,
}};
const struct fsdata_file file__index_html[] = { {
file__404_html,
data__index_html,
data__index_html + 12,
sizeof(data__index_html) - 12,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT,
}};
#define FS_ROOT file__index_html
#define FS_NUMFILES 3

View File

@@ -1,909 +0,0 @@
/**
* @file
* HTTP client
*/
/*
* Copyright (c) 2018 Simon Goldschmidt <goldsimon@gmx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*/
/**
* @defgroup httpc HTTP client
* @ingroup apps
* @todo:
* - persistent connections
* - select outgoing http version
* - optionally follow redirect
* - check request uri for invalid characters? (e.g. encode spaces)
* - IPv6 support
*/
#include "lwip/apps/http_client.h"
#include "lwip/altcp_tcp.h"
#include "lwip/dns.h"
#include "lwip/debug.h"
#include "lwip/mem.h"
#include "lwip/altcp_tls.h"
#include "lwip/init.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if LWIP_TCP && LWIP_CALLBACK_API
/**
* HTTPC_DEBUG: Enable debugging for HTTP client.
*/
#ifndef HTTPC_DEBUG
#define HTTPC_DEBUG LWIP_DBG_OFF
#endif
/** Set this to 1 to keep server name and uri in request state */
#ifndef HTTPC_DEBUG_REQUEST
#define HTTPC_DEBUG_REQUEST 0
#endif
/** This string is passed in the HTTP header as "User-Agent: " */
#ifndef HTTPC_CLIENT_AGENT
#define HTTPC_CLIENT_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)"
#endif
/* the various debug levels for this file */
#define HTTPC_DEBUG_TRACE (HTTPC_DEBUG | LWIP_DBG_TRACE)
#define HTTPC_DEBUG_STATE (HTTPC_DEBUG | LWIP_DBG_STATE)
#define HTTPC_DEBUG_WARN (HTTPC_DEBUG | LWIP_DBG_LEVEL_WARNING)
#define HTTPC_DEBUG_WARN_STATE (HTTPC_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
#define HTTPC_DEBUG_SERIOUS (HTTPC_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
#define HTTPC_POLL_INTERVAL 1
#define HTTPC_POLL_TIMEOUT 30 /* 15 seconds */
#define HTTPC_CONTENT_LEN_INVALID 0xFFFFFFFF
/* GET request basic */
#define HTTPC_REQ_11 "GET %s HTTP/1.1\r\n" /* URI */\
"User-Agent: %s\r\n" /* User-Agent */ \
"Accept: */*\r\n" \
"Connection: Close\r\n" /* we don't support persistent connections, yet */ \
"\r\n"
#define HTTPC_REQ_11_FORMAT(uri) HTTPC_REQ_11, uri, HTTPC_CLIENT_AGENT
/* GET request with host */
#define HTTPC_REQ_11_HOST "GET %s HTTP/1.1\r\n" /* URI */\
"User-Agent: %s\r\n" /* User-Agent */ \
"Accept: */*\r\n" \
"Host: %s\r\n" /* server name */ \
"Connection: Close\r\n" /* we don't support persistent connections, yet */ \
"\r\n"
#define HTTPC_REQ_11_HOST_FORMAT(uri, srv_name) HTTPC_REQ_11_HOST, uri, HTTPC_CLIENT_AGENT, srv_name
/* GET request with proxy */
#define HTTPC_REQ_11_PROXY "GET http://%s%s HTTP/1.1\r\n" /* HOST, URI */\
"User-Agent: %s\r\n" /* User-Agent */ \
"Accept: */*\r\n" \
"Host: %s\r\n" /* server name */ \
"Connection: Close\r\n" /* we don't support persistent connections, yet */ \
"\r\n"
#define HTTPC_REQ_11_PROXY_FORMAT(host, uri, srv_name) HTTPC_REQ_11_PROXY, host, uri, HTTPC_CLIENT_AGENT, srv_name
/* GET request with proxy (non-default server port) */
#define HTTPC_REQ_11_PROXY_PORT "GET http://%s:%d%s HTTP/1.1\r\n" /* HOST, host-port, URI */\
"User-Agent: %s\r\n" /* User-Agent */ \
"Accept: */*\r\n" \
"Host: %s\r\n" /* server name */ \
"Connection: Close\r\n" /* we don't support persistent connections, yet */ \
"\r\n"
#define HTTPC_REQ_11_PROXY_PORT_FORMAT(host, host_port, uri, srv_name) HTTPC_REQ_11_PROXY_PORT, host, host_port, uri, HTTPC_CLIENT_AGENT, srv_name
typedef enum ehttpc_parse_state {
HTTPC_PARSE_WAIT_FIRST_LINE = 0,
HTTPC_PARSE_WAIT_HEADERS,
HTTPC_PARSE_RX_DATA
} httpc_parse_state_t;
typedef struct _httpc_state
{
struct altcp_pcb* pcb;
ip_addr_t remote_addr;
u16_t remote_port;
int timeout_ticks;
struct pbuf *request;
struct pbuf *rx_hdrs;
u16_t rx_http_version;
u16_t rx_status;
altcp_recv_fn recv_fn;
const httpc_connection_t *conn_settings;
void* callback_arg;
u32_t rx_content_len;
u32_t hdr_content_len;
httpc_parse_state_t parse_state;
#if HTTPC_DEBUG_REQUEST
char* server_name;
char* uri;
#endif
} httpc_state_t;
/** Free http client state and deallocate all resources within */
static err_t
httpc_free_state(httpc_state_t* req)
{
struct altcp_pcb* tpcb;
if (req->request != NULL) {
pbuf_free(req->request);
req->request = NULL;
}
if (req->rx_hdrs != NULL) {
pbuf_free(req->rx_hdrs);
req->rx_hdrs = NULL;
}
tpcb = req->pcb;
mem_free(req);
req = NULL;
if (tpcb != NULL) {
err_t r;
altcp_arg(tpcb, NULL);
altcp_recv(tpcb, NULL);
altcp_err(tpcb, NULL);
altcp_poll(tpcb, NULL, 0);
altcp_sent(tpcb, NULL);
r = altcp_close(tpcb);
if (r != ERR_OK) {
altcp_abort(tpcb);
return ERR_ABRT;
}
}
return ERR_OK;
}
/** Close the connection: call finished callback and free the state */
static err_t
httpc_close(httpc_state_t* req, httpc_result_t result, u32_t server_response, err_t err)
{
if (req != NULL) {
if (req->conn_settings != NULL) {
if (req->conn_settings->result_fn != NULL) {
req->conn_settings->result_fn(req->callback_arg, result, req->rx_content_len, server_response, err);
}
}
return httpc_free_state(req);
}
return ERR_OK;
}
/** Parse http header response line 1 */
static err_t
http_parse_response_status(struct pbuf *p, u16_t *http_version, u16_t *http_status, u16_t *http_status_str_offset)
{
u16_t end1 = pbuf_memfind(p, "\r\n", 2, 0);
if (end1 != 0xFFFF) {
/* get parts of first line */
u16_t space1, space2;
space1 = pbuf_memfind(p, " ", 1, 0);
if (space1 != 0xFFFF) {
if ((pbuf_memcmp(p, 0, "HTTP/", 5) == 0) && (pbuf_get_at(p, 6) == '.')) {
char status_num[10];
size_t status_num_len;
/* parse http version */
u16_t version = pbuf_get_at(p, 5) - '0';
version <<= 8;
version |= pbuf_get_at(p, 7) - '0';
*http_version = version;
/* parse http status number */
space2 = pbuf_memfind(p, " ", 1, space1 + 1);
if (space2 != 0xFFFF) {
*http_status_str_offset = space2 + 1;
status_num_len = space2 - space1 - 1;
} else {
status_num_len = end1 - space1 - 1;
}
memset(status_num, 0, sizeof(status_num));
if (pbuf_copy_partial(p, status_num, (u16_t)status_num_len, space1 + 1) == status_num_len) {
int status = atoi(status_num);
if ((status > 0) && (status <= 0xFFFF)) {
*http_status = (u16_t)status;
return ERR_OK;
}
}
}
}
}
return ERR_VAL;
}
/** Wait for all headers to be received, return its length and content-length (if available) */
static err_t
http_wait_headers(struct pbuf *p, u32_t *content_length, u16_t *total_header_len)
{
u16_t end1 = pbuf_memfind(p, "\r\n\r\n", 4, 0);
if (end1 < (0xFFFF - 2)) {
/* all headers received */
/* check if we have a content length (@todo: case insensitive?) */
u16_t content_len_hdr;
*content_length = HTTPC_CONTENT_LEN_INVALID;
*total_header_len = end1 + 4;
content_len_hdr = pbuf_memfind(p, "Content-Length: ", 16, 0);
if (content_len_hdr != 0xFFFF) {
u16_t content_len_line_end = pbuf_memfind(p, "\r\n", 2, content_len_hdr);
if (content_len_line_end != 0xFFFF) {
char content_len_num[16];
u16_t content_len_num_len = (u16_t)(content_len_line_end - content_len_hdr - 16);
memset(content_len_num, 0, sizeof(content_len_num));
if (pbuf_copy_partial(p, content_len_num, content_len_num_len, content_len_hdr + 16) == content_len_num_len) {
int len = atoi(content_len_num);
if ((len >= 0) && ((u32_t)len < HTTPC_CONTENT_LEN_INVALID)) {
*content_length = (u32_t)len;
}
}
}
}
return ERR_OK;
}
return ERR_VAL;
}
/** http client tcp recv callback */
static err_t
httpc_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t r)
{
httpc_state_t* req = (httpc_state_t*)arg;
LWIP_UNUSED_ARG(r);
if (p == NULL) {
httpc_result_t result;
if (req->parse_state != HTTPC_PARSE_RX_DATA) {
/* did not get RX data yet */
result = HTTPC_RESULT_ERR_CLOSED;
} else if ((req->hdr_content_len != HTTPC_CONTENT_LEN_INVALID) &&
(req->hdr_content_len != req->rx_content_len)) {
/* header has been received with content length but not all data received */
result = HTTPC_RESULT_ERR_CONTENT_LEN;
} else {
/* receiving data and either all data received or no content length header */
result = HTTPC_RESULT_OK;
}
return httpc_close(req, result, req->rx_status, ERR_OK);
}
if (req->parse_state != HTTPC_PARSE_RX_DATA) {
if (req->rx_hdrs == NULL) {
req->rx_hdrs = p;
} else {
pbuf_cat(req->rx_hdrs, p);
}
if (req->parse_state == HTTPC_PARSE_WAIT_FIRST_LINE) {
u16_t status_str_off;
err_t err = http_parse_response_status(req->rx_hdrs, &req->rx_http_version, &req->rx_status, &status_str_off);
if (err == ERR_OK) {
/* don't care status string */
req->parse_state = HTTPC_PARSE_WAIT_HEADERS;
}
}
if (req->parse_state == HTTPC_PARSE_WAIT_HEADERS) {
u16_t total_header_len;
err_t err = http_wait_headers(req->rx_hdrs, &req->hdr_content_len, &total_header_len);
if (err == ERR_OK) {
struct pbuf *q;
/* full header received, send window update for header bytes and call into client callback */
altcp_recved(pcb, total_header_len);
if (req->conn_settings) {
if (req->conn_settings->headers_done_fn) {
err = req->conn_settings->headers_done_fn(req, req->callback_arg, req->rx_hdrs, total_header_len, req->hdr_content_len);
if (err != ERR_OK) {
return httpc_close(req, HTTPC_RESULT_LOCAL_ABORT, req->rx_status, err);
}
}
}
/* hide header bytes in pbuf */
q = pbuf_free_header(req->rx_hdrs, total_header_len);
p = q;
req->rx_hdrs = NULL;
/* go on with data */
req->parse_state = HTTPC_PARSE_RX_DATA;
}
}
}
if ((p != NULL) && (req->parse_state == HTTPC_PARSE_RX_DATA)) {
req->rx_content_len += p->tot_len;
if (req->recv_fn != NULL) {
/* directly return here: the connection migth already be aborted from the callback! */
return req->recv_fn(req->callback_arg, pcb, p, r);
} else {
altcp_recved(pcb, p->tot_len);
pbuf_free(p);
}
}
return ERR_OK;
}
/** http client tcp err callback */
static void
httpc_tcp_err(void *arg, err_t err)
{
httpc_state_t* req = (httpc_state_t*)arg;
if (req != NULL) {
/* pcb has already been deallocated */
req->pcb = NULL;
httpc_close(req, HTTPC_RESULT_ERR_CLOSED, 0, err);
}
}
/** http client tcp poll callback */
static err_t
httpc_tcp_poll(void *arg, struct altcp_pcb *pcb)
{
/* implement timeout */
httpc_state_t* req = (httpc_state_t*)arg;
LWIP_UNUSED_ARG(pcb);
if (req != NULL) {
if (req->timeout_ticks) {
req->timeout_ticks--;
}
if (!req->timeout_ticks) {
return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK);
}
}
return ERR_OK;
}
/** http client tcp sent callback */
static err_t
httpc_tcp_sent(void *arg, struct altcp_pcb *pcb, u16_t len)
{
/* nothing to do here for now */
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(len);
return ERR_OK;
}
/** http client tcp connected callback */
static err_t
httpc_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err)
{
err_t r;
httpc_state_t* req = (httpc_state_t*)arg;
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(err);
/* send request; last char is zero termination */
r = altcp_write(req->pcb, req->request->payload, req->request->len - 1, TCP_WRITE_FLAG_COPY);
if (r != ERR_OK) {
/* could not write the single small request -> fail, don't retry */
return httpc_close(req, HTTPC_RESULT_ERR_MEM, 0, r);
}
/* everything written, we can free the request */
pbuf_free(req->request);
req->request = NULL;
altcp_output(req->pcb);
return ERR_OK;
}
/** Start the http request when the server IP addr is known */
static err_t
httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr)
{
err_t err;
LWIP_ASSERT("req != NULL", req != NULL);
if (&req->remote_addr != ipaddr) {
/* fill in remote addr if called externally */
req->remote_addr = *ipaddr;
}
err = altcp_connect(req->pcb, &req->remote_addr, req->remote_port, httpc_tcp_connected);
if (err == ERR_OK) {
return ERR_OK;
}
LWIP_DEBUGF(HTTPC_DEBUG_WARN_STATE, ("tcp_connect failed: %d\n", (int)err));
return err;
}
#if LWIP_DNS
/** DNS callback
* If ipaddr is non-NULL, resolving succeeded and the request can be sent, otherwise it failed.
*/
static void
httpc_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
{
httpc_state_t* req = (httpc_state_t*)arg;
err_t err;
httpc_result_t result;
LWIP_UNUSED_ARG(hostname);
if (ipaddr != NULL) {
err = httpc_get_internal_addr(req, ipaddr);
if (err == ERR_OK) {
return;
}
result = HTTPC_RESULT_ERR_CONNECT;
} else {
LWIP_DEBUGF(HTTPC_DEBUG_WARN_STATE, ("httpc_dns_found: failed to resolve hostname: %s\n",
hostname));
result = HTTPC_RESULT_ERR_HOSTNAME;
err = ERR_ARG;
}
httpc_close(req, result, 0, err);
}
#endif /* LWIP_DNS */
/** Start the http request after converting 'server_name' to ip address (DNS or address string) */
static err_t
httpc_get_internal_dns(httpc_state_t* req, const char* server_name)
{
err_t err;
LWIP_ASSERT("req != NULL", req != NULL);
#if LWIP_DNS
err = dns_gethostbyname(server_name, &req->remote_addr, httpc_dns_found, req);
#else
err = ipaddr_aton(server_name, &req->remote_addr) ? ERR_OK : ERR_ARG;
#endif
if (err == ERR_OK) {
/* cached or IP-string */
err = httpc_get_internal_addr(req, &req->remote_addr);
} else if (err == ERR_INPROGRESS) {
return ERR_OK;
}
return err;
}
static int
httpc_create_request_string(const httpc_connection_t *settings, const char* server_name, int server_port, const char* uri,
int use_host, char *buffer, size_t buffer_size)
{
if (settings->use_proxy) {
LWIP_ASSERT("server_name != NULL", server_name != NULL);
if (server_port != HTTP_DEFAULT_PORT) {
return snprintf(buffer, buffer_size, HTTPC_REQ_11_PROXY_PORT_FORMAT(server_name, server_port, uri, server_name));
} else {
return snprintf(buffer, buffer_size, HTTPC_REQ_11_PROXY_FORMAT(server_name, uri, server_name));
}
} else if (use_host) {
LWIP_ASSERT("server_name != NULL", server_name != NULL);
return snprintf(buffer, buffer_size, HTTPC_REQ_11_HOST_FORMAT(uri, server_name));
} else {
return snprintf(buffer, buffer_size, HTTPC_REQ_11_FORMAT(uri));
}
}
/** Initialize the connection struct */
static err_t
httpc_init_connection_common(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, int use_host)
{
size_t alloc_len;
mem_size_t mem_alloc_len;
int req_len, req_len2;
httpc_state_t *req;
#if HTTPC_DEBUG_REQUEST
size_t server_name_len, uri_len;
#endif
LWIP_ASSERT("uri != NULL", uri != NULL);
/* get request len */
req_len = httpc_create_request_string(settings, server_name, server_port, uri, use_host, NULL, 0);
if ((req_len < 0) || (req_len > 0xFFFF)) {
return ERR_VAL;
}
/* alloc state and request in one block */
alloc_len = sizeof(httpc_state_t);
#if HTTPC_DEBUG_REQUEST
server_name_len = server_name ? strlen(server_name) : 0;
uri_len = strlen(uri);
alloc_len += server_name_len + 1 + uri_len + 1;
#endif
mem_alloc_len = (mem_size_t)alloc_len;
if ((mem_alloc_len < alloc_len) || (req_len + 1 > 0xFFFF)) {
return ERR_VAL;
}
req = (httpc_state_t*)mem_malloc((mem_size_t)alloc_len);
if(req == NULL) {
return ERR_MEM;
}
memset(req, 0, sizeof(httpc_state_t));
req->timeout_ticks = HTTPC_POLL_TIMEOUT;
req->request = pbuf_alloc(PBUF_RAW, (u16_t)(req_len + 1), PBUF_RAM);
if (req->request == NULL) {
httpc_free_state(req);
return ERR_MEM;
}
if (req->request->next != NULL) {
/* need a pbuf in one piece */
httpc_free_state(req);
return ERR_MEM;
}
req->hdr_content_len = HTTPC_CONTENT_LEN_INVALID;
#if HTTPC_DEBUG_REQUEST
req->server_name = (char*)(req + 1);
if (server_name) {
memcpy(req->server_name, server_name, server_name_len + 1);
}
req->uri = req->server_name + server_name_len + 1;
memcpy(req->uri, uri, uri_len + 1);
#endif
req->pcb = altcp_new(settings->altcp_allocator);
if(req->pcb == NULL) {
httpc_free_state(req);
return ERR_MEM;
}
req->remote_port = settings->use_proxy ? settings->proxy_port : server_port;
altcp_arg(req->pcb, req);
altcp_recv(req->pcb, httpc_tcp_recv);
altcp_err(req->pcb, httpc_tcp_err);
altcp_poll(req->pcb, httpc_tcp_poll, HTTPC_POLL_INTERVAL);
altcp_sent(req->pcb, httpc_tcp_sent);
/* set up request buffer */
req_len2 = httpc_create_request_string(settings, server_name, server_port, uri, use_host,
(char *)req->request->payload, req_len + 1);
if (req_len2 != req_len) {
httpc_free_state(req);
return ERR_VAL;
}
req->recv_fn = recv_fn;
req->conn_settings = settings;
req->callback_arg = callback_arg;
*connection = req;
return ERR_OK;
}
/**
* Initialize the connection struct
*/
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)
{
return httpc_init_connection_common(connection, settings, server_name, server_port, uri, recv_fn, callback_arg, 1);
}
/**
* Initialize the connection struct (from IP address)
*/
static err_t
httpc_init_connection_addr(httpc_state_t **connection, const httpc_connection_t *settings,
const ip_addr_t* server_addr, u16_t server_port, const char* uri,
altcp_recv_fn recv_fn, void* callback_arg)
{
char *server_addr_str = ipaddr_ntoa(server_addr);
if (server_addr_str == NULL) {
return ERR_VAL;
}
return httpc_init_connection_common(connection, settings, server_addr_str, server_port, uri,
recv_fn, callback_arg, 1);
}
/**
* @ingroup httpc
* HTTP client API: get a file by passing server IP address
*
* @param server_addr IP address of the server to connect
* @param port tcp port of the server
* @param uri uri to get from the server, remember leading "/"!
* @param settings connection settings (callbacks, proxy, etc.)
* @param recv_fn the http body (not the headers) are passed to this callback
* @param callback_arg argument passed to all the callbacks
* @param connection retreives the connection handle (to match in callbacks)
* @return ERR_OK if starting the request succeeds (callback_fn will be called later)
* or an error code
*/
err_t
httpc_get_file(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings,
altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection)
{
err_t err;
httpc_state_t* req;
LWIP_ERROR("invalid parameters", (server_addr != NULL) && (uri != NULL) && (recv_fn != NULL), return ERR_ARG;);
err = httpc_init_connection_addr(&req, settings, server_addr, port,
uri, recv_fn, callback_arg);
if (err != ERR_OK) {
return err;
}
if (settings->use_proxy) {
err = httpc_get_internal_addr(req, &settings->proxy_addr);
} else {
err = httpc_get_internal_addr(req, server_addr);
}
if(err != ERR_OK) {
httpc_free_state(req);
return err;
}
if (connection != NULL) {
*connection = req;
}
return ERR_OK;
}
/**
* @ingroup httpc
* HTTP client API: get a file by passing server name as string (DNS name or IP address string)
*
* @param server_name server name as string (DNS name or IP address string)
* @param port tcp port of the server
* @param uri uri to get from the server, remember leading "/"!
* @param settings connection settings (callbacks, proxy, etc.)
* @param recv_fn the http body (not the headers) are passed to this callback
* @param callback_arg argument passed to all the callbacks
* @param connection retreives the connection handle (to match in callbacks)
* @return ERR_OK if starting the request succeeds (callback_fn will be called later)
* or an error code
*/
err_t
httpc_get_file_dns(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings,
altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection)
{
err_t err;
httpc_state_t* req;
LWIP_ERROR("invalid parameters", (server_name != NULL) && (uri != NULL) && (recv_fn != NULL), return ERR_ARG;);
err = httpc_init_connection(&req, settings, server_name, port, uri, recv_fn, callback_arg);
if (err != ERR_OK) {
return err;
}
if (settings->use_proxy) {
err = httpc_get_internal_addr(req, &settings->proxy_addr);
} else {
err = httpc_get_internal_dns(req, server_name);
}
if(err != ERR_OK) {
httpc_free_state(req);
return err;
}
if (connection != NULL) {
*connection = req;
}
return ERR_OK;
}
#if LWIP_HTTPC_HAVE_FILE_IO
/* Implementation to disk via fopen/fwrite/fclose follows */
typedef struct _httpc_filestate
{
const char* local_file_name;
FILE *file;
httpc_connection_t settings;
const httpc_connection_t *client_settings;
void *callback_arg;
} httpc_filestate_t;
static void httpc_fs_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len,
u32_t srv_res, err_t err);
/** Initalize http client state for download to file system */
static err_t
httpc_fs_init(httpc_filestate_t **filestate_out, const char* local_file_name,
const httpc_connection_t *settings, void* callback_arg)
{
httpc_filestate_t *filestate;
size_t file_len, alloc_len;
FILE *f;
file_len = strlen(local_file_name);
alloc_len = sizeof(httpc_filestate_t) + file_len + 1;
filestate = (httpc_filestate_t *)mem_malloc((mem_size_t)alloc_len);
if (filestate == NULL) {
return ERR_MEM;
}
memset(filestate, 0, sizeof(httpc_filestate_t));
filestate->local_file_name = (const char *)(filestate + 1);
memcpy((char *)(filestate + 1), local_file_name, file_len + 1);
filestate->file = NULL;
filestate->client_settings = settings;
filestate->callback_arg = callback_arg;
/* copy client settings but override result callback */
memcpy(&filestate->settings, settings, sizeof(httpc_connection_t));
filestate->settings.result_fn = httpc_fs_result;
f = fopen(local_file_name, "wb");
if(f == NULL) {
/* could not open file */
mem_free(filestate);
return ERR_VAL;
}
filestate->file = f;
*filestate_out = filestate;
return ERR_OK;
}
/** Free http client state for download to file system */
static void
httpc_fs_free(httpc_filestate_t *filestate)
{
if (filestate != NULL) {
if (filestate->file != NULL) {
fclose(filestate->file);
filestate->file = NULL;
}
mem_free(filestate);
}
}
/** Connection closed (success or error) */
static void
httpc_fs_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len,
u32_t srv_res, err_t err)
{
httpc_filestate_t *filestate = (httpc_filestate_t *)arg;
if (filestate != NULL) {
if (filestate->client_settings->result_fn != NULL) {
filestate->client_settings->result_fn(filestate->callback_arg, httpc_result, rx_content_len,
srv_res, err);
}
httpc_fs_free(filestate);
}
}
/** tcp recv callback */
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;
struct pbuf* q;
LWIP_UNUSED_ARG(err);
LWIP_ASSERT("p != NULL", p != NULL);
for (q = p; q != NULL; q = q->next) {
fwrite(q->payload, 1, q->len, filestate->file);
}
altcp_recved(pcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/**
* @ingroup httpc
* HTTP client API: get a file to disk by passing server IP address
*
* @param server_addr IP address of the server to connect
* @param port tcp port of the server
* @param uri uri to get from the server, remember leading "/"!
* @param settings connection settings (callbacks, proxy, etc.)
* @param callback_arg argument passed to all the callbacks
* @param connection retreives the connection handle (to match in callbacks)
* @return ERR_OK if starting the request succeeds (callback_fn will be called later)
* or an error code
*/
err_t
httpc_get_file_to_disk(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings,
void* callback_arg, const char* local_file_name, httpc_state_t **connection)
{
err_t err;
httpc_state_t* req;
httpc_filestate_t *filestate;
LWIP_ERROR("invalid parameters", (server_addr != NULL) && (uri != NULL) && (local_file_name != NULL), return ERR_ARG;);
err = httpc_fs_init(&filestate, local_file_name, settings, callback_arg);
if (err != ERR_OK) {
return err;
}
err = httpc_init_connection_addr(&req, &filestate->settings, server_addr, port,
uri, httpc_fs_tcp_recv, filestate);
if (err != ERR_OK) {
httpc_fs_free(filestate);
return err;
}
if (settings->use_proxy) {
err = httpc_get_internal_addr(req, &settings->proxy_addr);
} else {
err = httpc_get_internal_addr(req, server_addr);
}
if(err != ERR_OK) {
httpc_fs_free(filestate);
httpc_free_state(req);
return err;
}
if (connection != NULL) {
*connection = req;
}
return ERR_OK;
}
/**
* @ingroup httpc
* HTTP client API: get a file to disk by passing server name as string (DNS name or IP address string)
*
* @param server_name server name as string (DNS name or IP address string)
* @param port tcp port of the server
* @param uri uri to get from the server, remember leading "/"!
* @param settings connection settings (callbacks, proxy, etc.)
* @param callback_arg argument passed to all the callbacks
* @param connection retreives the connection handle (to match in callbacks)
* @return ERR_OK if starting the request succeeds (callback_fn will be called later)
* or an error code
*/
err_t
httpc_get_file_dns_to_disk(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings,
void* callback_arg, const char* local_file_name, httpc_state_t **connection)
{
err_t err;
httpc_state_t* req;
httpc_filestate_t *filestate;
LWIP_ERROR("invalid parameters", (server_name != NULL) && (uri != NULL) && (local_file_name != NULL), return ERR_ARG;);
err = httpc_fs_init(&filestate, local_file_name, settings, callback_arg);
if (err != ERR_OK) {
return err;
}
err = httpc_init_connection(&req, &filestate->settings, server_name, port,
uri, httpc_fs_tcp_recv, filestate);
if (err != ERR_OK) {
httpc_fs_free(filestate);
return err;
}
if (settings->use_proxy) {
err = httpc_get_internal_addr(req, &settings->proxy_addr);
} else {
err = httpc_get_internal_dns(req, server_name);
}
if(err != ERR_OK) {
httpc_fs_free(filestate);
httpc_free_state(req);
return err;
}
if (connection != NULL) {
*connection = req;
}
return ERR_OK;
}
#endif /* LWIP_HTTPC_HAVE_FILE_IO */
#endif /* LWIP_TCP && LWIP_CALLBACK_API */

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +0,0 @@
#ifndef LWIP_HTTPD_STRUCTS_H
#define LWIP_HTTPD_STRUCTS_H
#include "lwip/apps/httpd.h"
#if LWIP_HTTPD_DYNAMIC_HEADERS
/** This struct is used for a list of HTTP header strings for various
* filename extensions. */
typedef struct {
const char *extension;
const char *content_type;
} tHTTPHeader;
/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and
* RFC 2616 HTTP/1.1 for header field definitions) */
static const char *const g_psHTTPHeaderStrings[] = {
"HTTP/1.0 200 OK\r\n",
"HTTP/1.0 404 File not found\r\n",
"HTTP/1.0 400 Bad Request\r\n",
"HTTP/1.0 501 Not Implemented\r\n",
"HTTP/1.1 200 OK\r\n",
"HTTP/1.1 404 File not found\r\n",
"HTTP/1.1 400 Bad Request\r\n",
"HTTP/1.1 501 Not Implemented\r\n",
"Content-Length: ",
"Connection: Close\r\n",
"Connection: keep-alive\r\n",
"Connection: keep-alive\r\nContent-Length: ",
"Server: "HTTPD_SERVER_AGENT"\r\n",
"\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
, "Connection: keep-alive\r\nContent-Length: 77\r\n\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
#endif
};
/* Indexes into the g_psHTTPHeaderStrings array */
#define HTTP_HDR_OK 0 /* 200 OK */
#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */
#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */
#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */
#define HTTP_HDR_OK_11 4 /* 200 OK */
#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */
#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */
#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */
#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/
#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */
#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */
#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/
#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */
#define DEFAULT_404_HTML 13 /* default 404 body */
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */
#endif
#define HTTP_CONTENT_TYPE(contenttype) "Content-Type: "contenttype"\r\n\r\n"
#define HTTP_CONTENT_TYPE_ENCODING(contenttype, encoding) "Content-Type: "contenttype"\r\nContent-Encoding: "encoding"\r\n\r\n"
#define HTTP_HDR_HTML HTTP_CONTENT_TYPE("text/html")
#define HTTP_HDR_SSI HTTP_CONTENT_TYPE("text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache")
#define HTTP_HDR_GIF HTTP_CONTENT_TYPE("image/gif")
#define HTTP_HDR_PNG HTTP_CONTENT_TYPE("image/png")
#define HTTP_HDR_JPG HTTP_CONTENT_TYPE("image/jpeg")
#define HTTP_HDR_BMP HTTP_CONTENT_TYPE("image/bmp")
#define HTTP_HDR_ICO HTTP_CONTENT_TYPE("image/x-icon")
#define HTTP_HDR_APP HTTP_CONTENT_TYPE("application/octet-stream")
#define HTTP_HDR_JS HTTP_CONTENT_TYPE("application/javascript")
#define HTTP_HDR_RA HTTP_CONTENT_TYPE("application/javascript")
#define HTTP_HDR_CSS HTTP_CONTENT_TYPE("text/css")
#define HTTP_HDR_SWF HTTP_CONTENT_TYPE("application/x-shockwave-flash")
#define HTTP_HDR_XML HTTP_CONTENT_TYPE("text/xml")
#define HTTP_HDR_PDF HTTP_CONTENT_TYPE("application/pdf")
#define HTTP_HDR_JSON HTTP_CONTENT_TYPE("application/json")
#define HTTP_HDR_CSV HTTP_CONTENT_TYPE("text/csv")
#define HTTP_HDR_TSV HTTP_CONTENT_TYPE("text/tsv")
#define HTTP_HDR_SVG HTTP_CONTENT_TYPE("image/svg+xml")
#define HTTP_HDR_SVGZ HTTP_CONTENT_TYPE_ENCODING("image/svg+xml", "gzip")
#define HTTP_HDR_DEFAULT_TYPE HTTP_CONTENT_TYPE("text/plain")
/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES
* and http://www.iana.org/assignments/media-types for registered content types
* and subtypes) */
static const tHTTPHeader g_psHTTPHeaders[] = {
{ "html", HTTP_HDR_HTML},
{ "htm", HTTP_HDR_HTML},
{ "shtml", HTTP_HDR_SSI},
{ "shtm", HTTP_HDR_SSI},
{ "ssi", HTTP_HDR_SSI},
{ "gif", HTTP_HDR_GIF},
{ "png", HTTP_HDR_PNG},
{ "jpg", HTTP_HDR_JPG},
{ "bmp", HTTP_HDR_BMP},
{ "ico", HTTP_HDR_ICO},
{ "class", HTTP_HDR_APP},
{ "cls", HTTP_HDR_APP},
{ "js", HTTP_HDR_JS},
{ "ram", HTTP_HDR_RA},
{ "css", HTTP_HDR_CSS},
{ "swf", HTTP_HDR_SWF},
{ "xml", HTTP_HDR_XML},
{ "xsl", HTTP_HDR_XML},
{ "pdf", HTTP_HDR_PDF},
{ "json", HTTP_HDR_JSON}
#ifdef HTTPD_ADDITIONAL_CONTENT_TYPES
/* If you need to add content types not listed here:
* #define HTTPD_ADDITIONAL_CONTENT_TYPES {"ct1", HTTP_CONTENT_TYPE("text/ct1")}, {"exe", HTTP_CONTENT_TYPE("application/exe")}
*/
, HTTPD_ADDITIONAL_CONTENT_TYPES
#endif
};
#define NUM_HTTP_HEADERS LWIP_ARRAYSIZE(g_psHTTPHeaders)
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
#if LWIP_HTTPD_SSI
static const char *const g_pcSSIExtensions[] = {
".shtml", ".shtm", ".ssi", ".xml", ".json"
};
#define NUM_SHTML_EXTENSIONS LWIP_ARRAYSIZE(g_pcSSIExtensions)
#endif /* LWIP_HTTPD_SSI */
#endif /* LWIP_HTTPD_STRUCTS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
This directory contains a script ('makefsdata') to create C code suitable for
httpd for given html pages (or other files) in a directory.
There is also a plain C console application doing the same and extended a bit.
Usage: htmlgen [targetdir] [-s] [-i]s
targetdir: relative or absolute path to files to convert
switch -s: toggle processing of subdirectories (default is on)
switch -e: exclude HTTP header from file (header is created at runtime, default is on)
switch -11: include HTTP 1.1 header (1.0 is default)
if targetdir not specified, makefsdata will attempt to
process files in subdirectory 'fs'.

View File

@@ -1,808 +0,0 @@
/*
Copyright (c) 2013-2017, tinydir authors:
- Cong Xu
- Lautis Sun
- Baudouin Feildel
- Andargor <andargor@yahoo.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TINYDIR_H
#define TINYDIR_H
#ifdef __cplusplus
extern "C" {
#endif
#if ((defined _UNICODE) && !(defined UNICODE))
#define UNICODE
#endif
#if ((defined UNICODE) && !(defined _UNICODE))
#define _UNICODE
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <tchar.h>
# pragma warning(push)
# pragma warning (disable : 4996)
#else
# include <dirent.h>
# include <libgen.h>
# include <sys/stat.h>
# include <stddef.h>
#endif
#ifdef __MINGW32__
# include <tchar.h>
#endif
/* types */
/* Windows UNICODE wide character support */
#if defined _MSC_VER || defined __MINGW32__
#define _tinydir_char_t TCHAR
#define TINYDIR_STRING(s) _TEXT(s)
#define _tinydir_strlen _tcslen
#define _tinydir_strcpy _tcscpy
#define _tinydir_strcat _tcscat
#define _tinydir_strcmp _tcscmp
#define _tinydir_strrchr _tcsrchr
#define _tinydir_strncmp _tcsncmp
#else
#define _tinydir_char_t char
#define TINYDIR_STRING(s) s
#define _tinydir_strlen strlen
#define _tinydir_strcpy strcpy
#define _tinydir_strcat strcat
#define _tinydir_strcmp strcmp
#define _tinydir_strrchr strrchr
#define _tinydir_strncmp strncmp
#endif
#if (defined _MSC_VER || defined __MINGW32__)
#include <windows.h>
#define _TINYDIR_PATH_MAX MAX_PATH
#elif defined __linux__
#include <linux/limits.h>
#define _TINYDIR_PATH_MAX PATH_MAX
#else
#define _TINYDIR_PATH_MAX 4096
#endif
#ifdef _MSC_VER
/* extra chars for the "\\*" mask */
# define _TINYDIR_PATH_EXTRA 2
#else
# define _TINYDIR_PATH_EXTRA 0
#endif
#define _TINYDIR_FILENAME_MAX 256
#if (defined _MSC_VER || defined __MINGW32__)
#define _TINYDIR_DRIVE_MAX 3
#endif
#ifdef _MSC_VER
# define _TINYDIR_FUNC static __inline
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# define _TINYDIR_FUNC static __inline__
#else
# define _TINYDIR_FUNC static inline
#endif
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
#ifdef TINYDIR_USE_READDIR_R
/* readdir_r is a POSIX-only function, and may not be available under various
* environments/settings, e.g. MinGW. Use readdir fallback */
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
_POSIX_SOURCE
# define _TINYDIR_HAS_READDIR_R
#endif
#if _POSIX_C_SOURCE >= 200112L
# define _TINYDIR_HAS_FPATHCONF
# include <unistd.h>
#endif
#if _BSD_SOURCE || _SVID_SOURCE || \
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
# define _TINYDIR_HAS_DIRFD
# include <sys/types.h>
#endif
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
defined _PC_NAME_MAX
# define _TINYDIR_USE_FPATHCONF
#endif
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
# define _TINYDIR_USE_READDIR
#endif
/* Use readdir by default */
#else
# define _TINYDIR_USE_READDIR
#endif
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
#ifndef _MSC_VER
#if (defined __MINGW32__) && (defined _UNICODE)
#define _TINYDIR_DIR _WDIR
#define _tinydir_dirent _wdirent
#define _tinydir_opendir _wopendir
#define _tinydir_readdir _wreaddir
#define _tinydir_closedir _wclosedir
#else
#define _TINYDIR_DIR DIR
#define _tinydir_dirent dirent
#define _tinydir_opendir opendir
#define _tinydir_readdir readdir
#define _tinydir_closedir closedir
#endif
#endif
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
#else
#error "Either define both alloc and free or none of them!"
#endif
#if !defined(_TINYDIR_MALLOC)
#define _TINYDIR_MALLOC(_size) malloc(_size)
#define _TINYDIR_FREE(_ptr) free(_ptr)
#endif /* !defined(_TINYDIR_MALLOC) */
typedef struct tinydir_file
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
_tinydir_char_t *extension;
int is_dir;
int is_reg;
#ifndef _MSC_VER
#ifdef __MINGW32__
struct _stat _s;
#else
struct stat _s;
#endif
#endif
} tinydir_file;
typedef struct tinydir_dir
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
int has_next;
size_t n_files;
tinydir_file *_files;
#ifdef _MSC_VER
HANDLE _h;
WIN32_FIND_DATA _f;
#else
_TINYDIR_DIR *_d;
struct _tinydir_dirent *_e;
#ifndef _TINYDIR_USE_READDIR
struct _tinydir_dirent *_ep;
#endif
#endif
} tinydir_dir;
/* declarations */
_TINYDIR_FUNC
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
_TINYDIR_FUNC
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
_TINYDIR_FUNC
void tinydir_close(tinydir_dir *dir);
_TINYDIR_FUNC
int tinydir_next(tinydir_dir *dir);
_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
_TINYDIR_FUNC
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
_TINYDIR_FUNC
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
_TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
_TINYDIR_FUNC
void _tinydir_get_ext(tinydir_file *file);
_TINYDIR_FUNC
int _tinydir_file_cmp(const void *a, const void *b);
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
_TINYDIR_FUNC
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
#endif
#endif
/* definitions*/
_TINYDIR_FUNC
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
{
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
int error;
int size; /* using int size */
#endif
#else
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
#endif
_tinydir_char_t *pathp;
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
{
errno = EINVAL;
return -1;
}
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
/* initialise dir */
dir->_files = NULL;
#ifdef _MSC_VER
dir->_h = INVALID_HANDLE_VALUE;
#else
dir->_d = NULL;
#ifndef _TINYDIR_USE_READDIR
dir->_ep = NULL;
#endif
#endif
tinydir_close(dir);
_tinydir_strcpy(dir->path, path);
/* Remove trailing slashes */
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
{
*pathp = TINYDIR_STRING('\0');
pathp++;
}
#ifdef _MSC_VER
_tinydir_strcpy(path_buf, dir->path);
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
#else
dir->_h = FindFirstFile(path_buf, &dir->_f);
#endif
if (dir->_h == INVALID_HANDLE_VALUE)
{
errno = ENOENT;
#else
dir->_d = _tinydir_opendir(path);
if (dir->_d == NULL)
{
#endif
goto bail;
}
/* read first file */
dir->has_next = 1;
#ifndef _MSC_VER
#ifdef _TINYDIR_USE_READDIR
dir->_e = _tinydir_readdir(dir->_d);
#else
/* allocate dirent buffer for readdir_r */
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
if (size == -1) return -1;
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
if (dir->_ep == NULL) return -1;
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
if (error != 0) return -1;
#endif
if (dir->_e == NULL)
{
dir->has_next = 0;
}
#endif
return 0;
bail:
tinydir_close(dir);
return -1;
}
_TINYDIR_FUNC
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
{
/* Count the number of files first, to pre-allocate the files array */
size_t n_files = 0;
if (tinydir_open(dir, path) == -1)
{
return -1;
}
while (dir->has_next)
{
n_files++;
if (tinydir_next(dir) == -1)
{
goto bail;
}
}
tinydir_close(dir);
if (tinydir_open(dir, path) == -1)
{
return -1;
}
dir->n_files = 0;
dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
if (dir->_files == NULL)
{
goto bail;
}
while (dir->has_next)
{
tinydir_file *p_file;
dir->n_files++;
p_file = &dir->_files[dir->n_files - 1];
if (tinydir_readfile(dir, p_file) == -1)
{
goto bail;
}
if (tinydir_next(dir) == -1)
{
goto bail;
}
/* Just in case the number of files has changed between the first and
second reads, terminate without writing into unallocated memory */
if (dir->n_files == n_files)
{
break;
}
}
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
return 0;
bail:
tinydir_close(dir);
return -1;
}
_TINYDIR_FUNC
void tinydir_close(tinydir_dir *dir)
{
if (dir == NULL)
{
return;
}
memset(dir->path, 0, sizeof(dir->path));
dir->has_next = 0;
dir->n_files = 0;
_TINYDIR_FREE(dir->_files);
dir->_files = NULL;
#ifdef _MSC_VER
if (dir->_h != INVALID_HANDLE_VALUE)
{
FindClose(dir->_h);
}
dir->_h = INVALID_HANDLE_VALUE;
#else
if (dir->_d)
{
_tinydir_closedir(dir->_d);
}
dir->_d = NULL;
dir->_e = NULL;
#ifndef _TINYDIR_USE_READDIR
_TINYDIR_FREE(dir->_ep);
dir->_ep = NULL;
#endif
#endif
}
_TINYDIR_FUNC
int tinydir_next(tinydir_dir *dir)
{
if (dir == NULL)
{
errno = EINVAL;
return -1;
}
if (!dir->has_next)
{
errno = ENOENT;
return -1;
}
#ifdef _MSC_VER
if (FindNextFile(dir->_h, &dir->_f) == 0)
#else
#ifdef _TINYDIR_USE_READDIR
dir->_e = _tinydir_readdir(dir->_d);
#else
if (dir->_ep == NULL)
{
return -1;
}
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
{
return -1;
}
#endif
if (dir->_e == NULL)
#endif
{
dir->has_next = 0;
#ifdef _MSC_VER
if (GetLastError() != ERROR_SUCCESS &&
GetLastError() != ERROR_NO_MORE_FILES)
{
tinydir_close(dir);
errno = EIO;
return -1;
}
#endif
}
return 0;
}
_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
{
if (dir == NULL || file == NULL)
{
errno = EINVAL;
return -1;
}
#ifdef _MSC_VER
if (dir->_h == INVALID_HANDLE_VALUE)
#else
if (dir->_e == NULL)
#endif
{
errno = ENOENT;
return -1;
}
if (_tinydir_strlen(dir->path) +
_tinydir_strlen(
#ifdef _MSC_VER
dir->_f.cFileName
#else
dir->_e->d_name
#endif
) + 1 + _TINYDIR_PATH_EXTRA >=
_TINYDIR_PATH_MAX)
{
/* the path for the file will be too long */
errno = ENAMETOOLONG;
return -1;
}
if (_tinydir_strlen(
#ifdef _MSC_VER
dir->_f.cFileName
#else
dir->_e->d_name
#endif
) >= _TINYDIR_FILENAME_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
_tinydir_strcpy(file->path, dir->path);
_tinydir_strcat(file->path, TINYDIR_STRING("/"));
_tinydir_strcpy(file->name,
#ifdef _MSC_VER
dir->_f.cFileName
#else
dir->_e->d_name
#endif
);
_tinydir_strcat(file->path, file->name);
#ifndef _MSC_VER
#ifdef __MINGW32__
if (_tstat(
#else
if (stat(
#endif
file->path, &file->_s) == -1)
{
return -1;
}
#endif
_tinydir_get_ext(file);
file->is_dir =
#ifdef _MSC_VER
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
#else
S_ISDIR(file->_s.st_mode);
#endif
file->is_reg =
#ifdef _MSC_VER
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
(
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
#endif
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
#endif
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
#else
S_ISREG(file->_s.st_mode);
#endif
return 0;
}
_TINYDIR_FUNC
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
{
if (dir == NULL || file == NULL)
{
errno = EINVAL;
return -1;
}
if (i >= dir->n_files)
{
errno = ENOENT;
return -1;
}
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
_tinydir_get_ext(file);
return 0;
}
_TINYDIR_FUNC
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
if (dir == NULL)
{
errno = EINVAL;
return -1;
}
if (i >= dir->n_files || !dir->_files[i].is_dir)
{
errno = ENOENT;
return -1;
}
_tinydir_strcpy(path, dir->_files[i].path);
tinydir_close(dir);
if (tinydir_open_sorted(dir, path) == -1)
{
return -1;
}
return 0;
}
/* Open a single file given its path */
_TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
{
tinydir_dir dir;
int result = 0;
int found = 0;
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
_tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
_tinydir_char_t *dir_name;
_tinydir_char_t *base_name;
#if (defined _MSC_VER || defined __MINGW32__)
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
#endif
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
{
errno = EINVAL;
return -1;
}
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
/* Get the parent path */
#if (defined _MSC_VER || defined __MINGW32__)
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
_tsplitpath_s(
path,
drive_buf, _TINYDIR_DRIVE_MAX,
dir_name_buf, _TINYDIR_FILENAME_MAX,
file_name_buf, _TINYDIR_FILENAME_MAX,
ext_buf, _TINYDIR_FILENAME_MAX);
#else
_tsplitpath(
path,
drive_buf,
dir_name_buf,
file_name_buf,
ext_buf);
#endif
/* _splitpath_s not work fine with only filename and widechar support */
#ifdef _UNICODE
if (drive_buf[0] == L'\xFEFE')
drive_buf[0] = '\0';
if (dir_name_buf[0] == L'\xFEFE')
dir_name_buf[0] = '\0';
#endif
if (errno)
{
errno = EINVAL;
return -1;
}
/* Emulate the behavior of dirname by returning "." for dir name if it's
empty */
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
{
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
}
/* Concatenate the drive letter and dir name to form full dir name */
_tinydir_strcat(drive_buf, dir_name_buf);
dir_name = drive_buf;
/* Concatenate the file name and extension to form base name */
_tinydir_strcat(file_name_buf, ext_buf);
base_name = file_name_buf;
#else
_tinydir_strcpy(dir_name_buf, path);
dir_name = dirname(dir_name_buf);
_tinydir_strcpy(file_name_buf, path);
base_name =basename(file_name_buf);
#endif
/* Open the parent directory */
if (tinydir_open(&dir, dir_name) == -1)
{
return -1;
}
/* Read through the parent directory and look for the file */
while (dir.has_next)
{
if (tinydir_readfile(&dir, file) == -1)
{
result = -1;
goto bail;
}
if (_tinydir_strcmp(file->name, base_name) == 0)
{
/* File found */
found = 1;
break;
}
tinydir_next(&dir);
}
if (!found)
{
result = -1;
errno = ENOENT;
}
bail:
tinydir_close(&dir);
return result;
}
_TINYDIR_FUNC
void _tinydir_get_ext(tinydir_file *file)
{
_tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
if (period == NULL)
{
file->extension = &(file->name[_tinydir_strlen(file->name)]);
}
else
{
file->extension = period + 1;
}
}
_TINYDIR_FUNC
int _tinydir_file_cmp(const void *a, const void *b)
{
const tinydir_file *fa = (const tinydir_file *)a;
const tinydir_file *fb = (const tinydir_file *)b;
if (fa->is_dir != fb->is_dir)
{
return -(fa->is_dir - fb->is_dir);
}
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
}
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
/*
The following authored by Ben Hutchings <ben@decadent.org.uk>
from https://womble.decadent.org.uk/readdir_r-advisory.html
*/
/* Calculate the required buffer size (in bytes) for directory *
* entries read from the given directory handle. Return -1 if this *
* this cannot be done. *
* *
* This code does not trust values of NAME_MAX that are less than *
* 255, since some systems (including at least HP-UX) incorrectly *
* define it to be a smaller value. */
_TINYDIR_FUNC
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
{
long name_max;
size_t name_end;
/* parameter may be unused */
(void)dirp;
#if defined _TINYDIR_USE_FPATHCONF
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
if (name_max == -1)
#if defined(NAME_MAX)
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
return (size_t)(-1);
#endif
#elif defined(NAME_MAX)
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
#error "buffer size for readdir_r cannot be determined"
#endif
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
return (name_end > sizeof(struct _tinydir_dirent) ?
name_end : sizeof(struct _tinydir_dirent));
}
#endif
#endif
#ifdef __cplusplus
}
#endif
# if defined (_MSC_VER)
# pragma warning(pop)
# endif
#endif

View File

@@ -1,841 +0,0 @@
/**
* @file
* lwIP iPerf server implementation
*/
/**
* @defgroup iperf Iperf server
* @ingroup apps
*
* This is a simple performance measuring client/server to check your bandwith using
* iPerf2 on a PC as server/client.
* It is currently a minimal implementation providing a TCP client/server only.
*
* @todo:
* - implement UDP mode
* - protect combined sessions handling (via 'related_master_state') against reallocation
* (this is a pointer address, currently, so if the same memory is allocated again,
* session pairs (tx/rx) can be confused on reallocation)
*/
/*
* Copyright (c) 2014 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*/
#include "lwip/apps/lwiperf.h"
#include "lwip/tcp.h"
#include "lwip/sys.h"
#include <string.h>
/* Currently, only TCP is implemented */
#if LWIP_TCP && LWIP_CALLBACK_API
/** Specify the idle timeout (in seconds) after that the test fails */
#ifndef LWIPERF_TCP_MAX_IDLE_SEC
#define LWIPERF_TCP_MAX_IDLE_SEC 10U
#endif
#if LWIPERF_TCP_MAX_IDLE_SEC > 255
#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t
#endif
/** Change this if you don't want to lwiperf to listen to any IP version */
#ifndef LWIPERF_SERVER_IP_TYPE
#define LWIPERF_SERVER_IP_TYPE IPADDR_TYPE_ANY
#endif
/* File internal memory allocation (struct lwiperf_*): this defaults to
the heap */
#ifndef LWIPERF_ALLOC
#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type))
#define LWIPERF_FREE(type, item) mem_free(item)
#endif
/** If this is 1, check that received data has the correct format */
#ifndef LWIPERF_CHECK_RX_DATA
#define LWIPERF_CHECK_RX_DATA 0
#endif
/** This is the Iperf settings struct sent from the client */
typedef struct _lwiperf_settings {
#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000
#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001
u32_t flags;
u32_t num_threads; /* unused for now */
u32_t remote_port;
u32_t buffer_len; /* unused for now */
u32_t win_band; /* TCP window / UDP rate: unused for now */
u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */
} lwiperf_settings_t;
/** Basic connection handle */
struct _lwiperf_state_base;
typedef struct _lwiperf_state_base lwiperf_state_base_t;
struct _lwiperf_state_base {
/* linked list */
lwiperf_state_base_t *next;
/* 1=tcp, 0=udp */
u8_t tcp;
/* 1=server, 0=client */
u8_t server;
/* master state used to abort sessions (e.g. listener, main client) */
lwiperf_state_base_t *related_master_state;
};
/** Connection handle for a TCP iperf session */
typedef struct _lwiperf_state_tcp {
lwiperf_state_base_t base;
struct tcp_pcb *server_pcb;
struct tcp_pcb *conn_pcb;
u32_t time_started;
lwiperf_report_fn report_fn;
void *report_arg;
u8_t poll_count;
u8_t next_num;
/* 1=start server when client is closed */
u8_t client_tradeoff_mode;
u32_t bytes_transferred;
lwiperf_settings_t settings;
u8_t have_settings_buf;
u8_t specific_remote;
ip_addr_t remote_addr;
} lwiperf_state_tcp_t;
/** List of active iperf sessions */
static lwiperf_state_base_t *lwiperf_all_connections;
/** A const buffer to send from: we want to measure sending, not copying! */
static const u8_t lwiperf_txbuf_const[1600] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};
static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb);
static void lwiperf_tcp_err(void *arg, err_t err);
static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port,
lwiperf_report_fn report_fn, void *report_arg,
lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state);
/** Add an iperf session to the 'active' list */
static void
lwiperf_list_add(lwiperf_state_base_t *item)
{
item->next = lwiperf_all_connections;
lwiperf_all_connections = item;
}
/** Remove an iperf session from the 'active' list */
static void
lwiperf_list_remove(lwiperf_state_base_t *item)
{
lwiperf_state_base_t *prev = NULL;
lwiperf_state_base_t *iter;
for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) {
if (iter == item) {
if (prev == NULL) {
lwiperf_all_connections = iter->next;
} else {
prev->next = iter->next;
}
/* @debug: ensure this item is listed only once */
for (iter = iter->next; iter != NULL; iter = iter->next) {
LWIP_ASSERT("duplicate entry", iter != item);
}
break;
}
}
}
static lwiperf_state_base_t *
lwiperf_list_find(lwiperf_state_base_t *item)
{
lwiperf_state_base_t *iter;
for (iter = lwiperf_all_connections; iter != NULL; iter = iter->next) {
if (iter == item) {
return item;
}
}
return NULL;
}
/** Call the report function of an iperf tcp session */
static void
lwip_tcp_conn_report(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type)
{
if ((conn != NULL) && (conn->report_fn != NULL)) {
u32_t now, duration_ms, bandwidth_kbitpsec;
now = sys_now();
duration_ms = now - conn->time_started;
if (duration_ms == 0) {
bandwidth_kbitpsec = 0;
} else {
bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U;
}
conn->report_fn(conn->report_arg, report_type,
&conn->conn_pcb->local_ip, conn->conn_pcb->local_port,
&conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port,
conn->bytes_transferred, duration_ms, bandwidth_kbitpsec);
}
}
/** Close an iperf tcp session */
static void
lwiperf_tcp_close(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type)
{
err_t err;
lwiperf_list_remove(&conn->base);
lwip_tcp_conn_report(conn, report_type);
if (conn->conn_pcb != NULL) {
tcp_arg(conn->conn_pcb, NULL);
tcp_poll(conn->conn_pcb, NULL, 0);
tcp_sent(conn->conn_pcb, NULL);
tcp_recv(conn->conn_pcb, NULL);
tcp_err(conn->conn_pcb, NULL);
err = tcp_close(conn->conn_pcb);
if (err != ERR_OK) {
/* don't want to wait for free memory here... */
tcp_abort(conn->conn_pcb);
}
} else {
/* no conn pcb, this is the listener pcb */
err = tcp_close(conn->server_pcb);
LWIP_ASSERT("error", err == ERR_OK);
}
LWIPERF_FREE(lwiperf_state_tcp_t, conn);
}
/** Try to send more data on an iperf tcp session */
static err_t
lwiperf_tcp_client_send_more(lwiperf_state_tcp_t *conn)
{
int send_more;
err_t err;
u16_t txlen;
u16_t txlen_max;
void *txptr;
u8_t apiflags;
LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));
do {
send_more = 0;
if (conn->settings.amount & PP_HTONL(0x80000000)) {
/* this session is time-limited */
u32_t now = sys_now();
u32_t diff_ms = now - conn->time_started;
u32_t time = (u32_t) - (s32_t)lwip_htonl(conn->settings.amount);
u32_t time_ms = time * 10;
if (diff_ms >= time_ms) {
/* time specified by the client is over -> close the connection */
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
return ERR_OK;
}
} else {
/* this session is byte-limited */
u32_t amount_bytes = lwip_htonl(conn->settings.amount);
/* @todo: this can send up to 1*MSS more than requested... */
if (amount_bytes >= conn->bytes_transferred) {
/* all requested bytes transferred -> close the connection */
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
return ERR_OK;
}
}
if (conn->bytes_transferred < 24) {
/* transmit the settings a first time */
txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred];
txlen_max = (u16_t)(24 - conn->bytes_transferred);
apiflags = TCP_WRITE_FLAG_COPY;
} else if (conn->bytes_transferred < 48) {
/* transmit the settings a second time */
txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred - 24];
txlen_max = (u16_t)(48 - conn->bytes_transferred);
apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
send_more = 1;
} else {
/* transmit data */
/* @todo: every x bytes, transmit the settings again */
txptr = LWIP_CONST_CAST(void *, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
txlen_max = TCP_MSS;
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
txlen_max = TCP_MSS - 24;
}
apiflags = 0; /* no copying needed */
send_more = 1;
}
txlen = txlen_max;
do {
err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
if (err == ERR_MEM) {
txlen /= 2;
}
} while ((err == ERR_MEM) && (txlen >= (TCP_MSS / 2)));
if (err == ERR_OK) {
conn->bytes_transferred += txlen;
} else {
send_more = 0;
}
} while (send_more);
tcp_output(conn->conn_pcb);
return ERR_OK;
}
/** TCP sent callback, try to send more data */
static err_t
lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
/* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
LWIP_UNUSED_ARG(len);
conn->poll_count = 0;
return lwiperf_tcp_client_send_more(conn);
}
/** TCP connected callback (active connection), send data now */
static err_t
lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (err != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
return ERR_OK;
}
conn->poll_count = 0;
conn->time_started = sys_now();
return lwiperf_tcp_client_send_more(conn);
}
/** Start TCP connection back to the client (either parallel or after the
* receive test has finished.
*/
static err_t
lwiperf_tx_start_impl(const ip_addr_t *remote_ip, u16_t remote_port, lwiperf_settings_t *settings, lwiperf_report_fn report_fn,
void *report_arg, lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **new_conn)
{
err_t err;
lwiperf_state_tcp_t *client_conn;
struct tcp_pcb *newpcb;
ip_addr_t remote_addr;
LWIP_ASSERT("remote_ip != NULL", remote_ip != NULL);
LWIP_ASSERT("remote_ip != NULL", settings != NULL);
LWIP_ASSERT("new_conn != NULL", new_conn != NULL);
*new_conn = NULL;
client_conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (client_conn == NULL) {
return ERR_MEM;
}
newpcb = tcp_new_ip_type(IP_GET_TYPE(remote_ip));
if (newpcb == NULL) {
LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
return ERR_MEM;
}
memset(client_conn, 0, sizeof(lwiperf_state_tcp_t));
client_conn->base.tcp = 1;
client_conn->base.related_master_state = related_master_state;
client_conn->conn_pcb = newpcb;
client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */
client_conn->report_fn = report_fn;
client_conn->report_arg = report_arg;
client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
client_conn->bytes_transferred = 0;
memcpy(&client_conn->settings, settings, sizeof(*settings));
client_conn->have_settings_buf = 1;
tcp_arg(newpcb, client_conn);
tcp_sent(newpcb, lwiperf_tcp_client_sent);
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
tcp_err(newpcb, lwiperf_tcp_err);
ip_addr_copy(remote_addr, *remote_ip);
err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
if (err != ERR_OK) {
lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
return err;
}
lwiperf_list_add(&client_conn->base);
*new_conn = client_conn;
return ERR_OK;
}
static err_t
lwiperf_tx_start_passive(lwiperf_state_tcp_t *conn)
{
err_t ret;
lwiperf_state_tcp_t *new_conn = NULL;
u16_t remote_port = (u16_t)lwip_htonl(conn->settings.remote_port);
ret = lwiperf_tx_start_impl(&conn->conn_pcb->remote_ip, remote_port, &conn->settings, conn->report_fn, conn->report_arg,
conn->base.related_master_state, &new_conn);
if (ret == ERR_OK) {
LWIP_ASSERT("new_conn != NULL", new_conn != NULL);
new_conn->settings.flags = 0; /* prevent the remote side starting back as client again */
}
return ret;
}
/** Receive data on an iperf tcp session */
static err_t
lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
u8_t tmp;
u16_t tot_len;
u32_t packet_idx;
struct pbuf *q;
lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (err != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
return ERR_OK;
}
if (p == NULL) {
/* connection closed -> test done */
if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) == 0) {
/* client requested transmission after end of test */
lwiperf_tx_start_passive(conn);
}
}
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER);
return ERR_OK;
}
tot_len = p->tot_len;
conn->poll_count = 0;
if ((!conn->have_settings_buf) || ((conn->bytes_transferred - 24) % (1024 * 128) == 0)) {
/* wait for 24-byte header */
if (p->tot_len < sizeof(lwiperf_settings_t)) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_OK;
}
if (!conn->have_settings_buf) {
if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
pbuf_free(p);
return ERR_OK;
}
conn->have_settings_buf = 1;
if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) {
/* client requested parallel transmission test */
err_t err2 = lwiperf_tx_start_passive(conn);
if (err2 != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR);
pbuf_free(p);
return ERR_OK;
}
}
}
} else {
if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_OK;
}
}
}
conn->bytes_transferred += sizeof(lwiperf_settings_t);
if (conn->bytes_transferred <= 24) {
conn->time_started = sys_now();
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
conn->next_num = 4; /* 24 bytes received... */
tmp = pbuf_remove_header(p, 24);
LWIP_ASSERT("pbuf_remove_header failed", tmp == 0);
LWIP_UNUSED_ARG(tmp); /* for LWIP_NOASSERT */
}
packet_idx = 0;
for (q = p; q != NULL; q = q->next) {
#if LWIPERF_CHECK_RX_DATA
const u8_t *payload = (const u8_t *)q->payload;
u16_t i;
for (i = 0; i < q->len; i++) {
u8_t val = payload[i];
u8_t num = val - '0';
if (num == conn->next_num) {
conn->next_num++;
if (conn->next_num == 10) {
conn->next_num = 0;
}
} else {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_OK;
}
}
#endif
packet_idx += q->len;
}
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
conn->bytes_transferred += packet_idx;
tcp_recved(tpcb, tot_len);
pbuf_free(p);
return ERR_OK;
}
/** Error callback, iperf tcp session aborted */
static void
lwiperf_tcp_err(void *arg, err_t err)
{
lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
LWIP_UNUSED_ARG(err);
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
}
/** TCP poll callback, try to send more data */
static err_t
lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb)
{
lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
return ERR_OK; /* lwiperf_tcp_close frees conn */
}
if (!conn->base.server) {
lwiperf_tcp_client_send_more(conn);
}
return ERR_OK;
}
/** This is called when a new client connects for an iperf tcp session */
static err_t
lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
lwiperf_state_tcp_t *s, *conn;
if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) {
return ERR_VAL;
}
s = (lwiperf_state_tcp_t *)arg;
LWIP_ASSERT("invalid session", s->base.server);
LWIP_ASSERT("invalid listen pcb", s->server_pcb != NULL);
LWIP_ASSERT("invalid conn pcb", s->conn_pcb == NULL);
if (s->specific_remote) {
LWIP_ASSERT("s->base.related_master_state != NULL", s->base.related_master_state != NULL);
if (!ip_addr_cmp(&newpcb->remote_ip, &s->remote_addr)) {
/* this listener belongs to a client session, and this is not the correct remote */
return ERR_VAL;
}
} else {
LWIP_ASSERT("s->base.related_master_state == NULL", s->base.related_master_state == NULL);
}
conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (conn == NULL) {
return ERR_MEM;
}
memset(conn, 0, sizeof(lwiperf_state_tcp_t));
conn->base.tcp = 1;
conn->base.server = 1;
conn->base.related_master_state = &s->base;
conn->conn_pcb = newpcb;
conn->time_started = sys_now();
conn->report_fn = s->report_fn;
conn->report_arg = s->report_arg;
/* setup the tcp rx connection */
tcp_arg(newpcb, conn);
tcp_recv(newpcb, lwiperf_tcp_recv);
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
tcp_err(conn->conn_pcb, lwiperf_tcp_err);
if (s->specific_remote) {
/* this listener belongs to a client, so make the client the master of the newly created connection */
conn->base.related_master_state = s->base.related_master_state;
/* if dual mode or (tradeoff mode AND client is done): close the listener */
if (!s->client_tradeoff_mode || !lwiperf_list_find(s->base.related_master_state)) {
/* prevent report when closing: this is expected */
s->report_fn = NULL;
lwiperf_tcp_close(s, LWIPERF_TCP_ABORTED_LOCAL);
}
}
lwiperf_list_add(&conn->base);
return ERR_OK;
}
/**
* @ingroup iperf
* Start a TCP iperf server on the default TCP port (5001) and listen for
* incoming connections from iperf clients.
*
* @returns a connection handle that can be used to abort the server
* by calling @ref lwiperf_abort()
*/
void *
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg)
{
return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
report_fn, report_arg);
}
/**
* @ingroup iperf
* Start a TCP iperf server on a specific IP address and port and listen for
* incoming connections from iperf clients.
*
* @returns a connection handle that can be used to abort the server
* by calling @ref lwiperf_abort()
*/
void *
lwiperf_start_tcp_server(const ip_addr_t *local_addr, u16_t local_port,
lwiperf_report_fn report_fn, void *report_arg)
{
err_t err;
lwiperf_state_tcp_t *state = NULL;
err = lwiperf_start_tcp_server_impl(local_addr, local_port, report_fn, report_arg,
NULL, &state);
if (err == ERR_OK) {
return state;
}
return NULL;
}
static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port,
lwiperf_report_fn report_fn, void *report_arg,
lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state)
{
err_t err;
struct tcp_pcb *pcb;
lwiperf_state_tcp_t *s;
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("state != NULL", state != NULL);
if (local_addr == NULL) {
return ERR_ARG;
}
s = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (s == NULL) {
return ERR_MEM;
}
memset(s, 0, sizeof(lwiperf_state_tcp_t));
s->base.tcp = 1;
s->base.server = 1;
s->base.related_master_state = related_master_state;
s->report_fn = report_fn;
s->report_arg = report_arg;
pcb = tcp_new_ip_type(LWIPERF_SERVER_IP_TYPE);
if (pcb == NULL) {
return ERR_MEM;
}
err = tcp_bind(pcb, local_addr, local_port);
if (err != ERR_OK) {
return err;
}
s->server_pcb = tcp_listen_with_backlog(pcb, 1);
if (s->server_pcb == NULL) {
if (pcb != NULL) {
tcp_close(pcb);
}
LWIPERF_FREE(lwiperf_state_tcp_t, s);
return ERR_MEM;
}
pcb = NULL;
tcp_arg(s->server_pcb, s);
tcp_accept(s->server_pcb, lwiperf_tcp_accept);
lwiperf_list_add(&s->base);
*state = s;
return ERR_OK;
}
/**
* @ingroup iperf
* Start a TCP iperf client to the default TCP port (5001).
*
* @returns a connection handle that can be used to abort the client
* by calling @ref lwiperf_abort()
*/
void* lwiperf_start_tcp_client_default(const ip_addr_t* remote_addr,
lwiperf_report_fn report_fn, void* report_arg)
{
return lwiperf_start_tcp_client(remote_addr, LWIPERF_TCP_PORT_DEFAULT, LWIPERF_CLIENT,
report_fn, report_arg);
}
/**
* @ingroup iperf
* Start a TCP iperf client to a specific IP address and port.
*
* @returns a connection handle that can be used to abort the client
* by calling @ref lwiperf_abort()
*/
void* lwiperf_start_tcp_client(const ip_addr_t* remote_addr, u16_t remote_port,
enum lwiperf_client_type type, lwiperf_report_fn report_fn, void* report_arg)
{
err_t ret;
lwiperf_settings_t settings;
lwiperf_state_tcp_t *state = NULL;
memset(&settings, 0, sizeof(settings));
switch (type) {
case LWIPERF_CLIENT:
/* Unidirectional tx only test */
settings.flags = 0;
break;
case LWIPERF_DUAL:
/* Do a bidirectional test simultaneously */
settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST | LWIPERF_FLAGS_ANSWER_NOW);
break;
case LWIPERF_TRADEOFF:
/* Do a bidirectional test individually */
settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST);
break;
default:
/* invalid argument */
return NULL;
}
settings.num_threads = htonl(1);
settings.remote_port = htonl(LWIPERF_TCP_PORT_DEFAULT);
/* TODO: implement passing duration/amount of bytes to transfer */
settings.amount = htonl((u32_t)-1000);
ret = lwiperf_tx_start_impl(remote_addr, remote_port, &settings, report_fn, report_arg, NULL, &state);
if (ret == ERR_OK) {
LWIP_ASSERT("state != NULL", state != NULL);
if (type != LWIPERF_CLIENT) {
/* start corresponding server now */
lwiperf_state_tcp_t *server = NULL;
ret = lwiperf_start_tcp_server_impl(&state->conn_pcb->local_ip, LWIPERF_TCP_PORT_DEFAULT,
report_fn, report_arg, (lwiperf_state_base_t *)state, &server);
if (ret != ERR_OK) {
/* starting server failed, abort client */
lwiperf_abort(state);
return NULL;
}
/* make this server accept one connection only */
server->specific_remote = 1;
server->remote_addr = state->conn_pcb->remote_ip;
if (type == LWIPERF_TRADEOFF) {
/* tradeoff means that the remote host connects only after the client is done,
so keep the listen pcb open until the client is done */
server->client_tradeoff_mode = 1;
}
}
return state;
}
return NULL;
}
/**
* @ingroup iperf
* Abort an iperf session (handle returned by lwiperf_start_tcp_server*())
*/
void
lwiperf_abort(void *lwiperf_session)
{
lwiperf_state_base_t *i, *dealloc, *last = NULL;
LWIP_ASSERT_CORE_LOCKED();
for (i = lwiperf_all_connections; i != NULL; ) {
if ((i == lwiperf_session) || (i->related_master_state == lwiperf_session)) {
dealloc = i;
i = i->next;
if (last != NULL) {
last->next = i;
}
LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */
} else {
last = i;
i = i->next;
}
}
}
#endif /* LWIP_TCP && LWIP_CALLBACK_API */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More