mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-27 15:24:11 +08:00
[remove] the doc folder of lwIP 2.1.2
Signed-off-by: liuxianliang <liuxianliang@rt-thread.com>
This commit is contained in:
@@ -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.
|
|
||||||
@@ -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 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
doxygen lwip.Doxyfile
|
|
||||||
@@ -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
@@ -1,403 +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 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.
|
|
||||||
*/
|
|
||||||
@@ -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>
|
|
||||||
Binary file not shown.
@@ -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)
|
|
||||||
@@ -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)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
|
||||||
Reference in New Issue
Block a user