Initial revision
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..7b40fe6
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,284 @@
+(0.5.3) Changes since version 0.5.2
+
+ ++ Bugfixes:
+
+ * memp_malloc(MEMP_API_MSG) could fail with multiple application
+ threads because it wasn't protected by semaphores.
+
+ ++ Other changes:
+
+ * struct ip_addr now packed.
+
+ * The name of the time variable in arp.c has been changed to ctime
+ to avoid conflicts with the time() function.
+
+(0.5.2) Changes since version 0.5.1
+
+ ++ New features:
+
+ * A new TCP function, tcp_tmr(), now handles both TCP timers.
+
+ ++ Bugfixes:
+
+ * A bug in tcp_parseopt() could cause the stack to hang because of a
+ malformed TCP option.
+
+ * The address of new connections in the accept() function in the BSD
+ socket library was not handled correctly.
+
+ * pbuf_dechain() did not update the ->tot_len field of the tail.
+
+ * Aborted TCP connections were not handled correctly in all
+ situations.
+
+ ++ Other changes:
+
+ * All protocol header structs are now packed.
+
+ * The ->len field in the tcp_seg structure now counts the actual
+ amount of data, and does not add one for SYN and FIN segments.
+
+(0.5.1) Changes since version 0.5.0
+
+ ++ New features:
+
+ * Possible to run as a user process under Linux.
+
+ * Preliminary support for cross platform packed structs.
+
+ * ARP timer now implemented.
+
+ ++ Bugfixes:
+
+ * TCP output queue length was badly initialized when opening
+ connections.
+
+ * TCP delayed ACKs were not sent correctly.
+
+ * Explicit initialization of BSS segment variables.
+
+ * read() in BSD socket library could drop data.
+
+ * Problems with memory alignment.
+
+ * Situations when all TCP buffers were used could lead to
+ starvation.
+
+ * TCP MSS option wasn't parsed correctly.
+
+ * Problems with UDP checksum calculation.
+
+ * IP multicast address tests had endianess problems.
+
+ * ARP requests had wrong destination hardware address.
+
+ ++ Other changes:
+
+ * struct eth_addr changed from u16_t[3] array to u8_t[6].
+
+ * A ->linkoutput() member was added to struct netif.
+
+ * TCP and UDP ->dest_* struct members where changed to ->remote_*.
+
+ * ntoh* macros are now null definitions for big endian CPUs.
+
+(0.5.0) Changes since version 0.4.2
+
+ ++ New features:
+
+ * Redesigned operating system emulation layer to make porting easier.
+
+ * Better control over TCP output buffers.
+
+ * Documenation added.
+
+ ++ Bugfixes:
+
+ * Locking issues in buffer management.
+
+ * Bugfixes in the sequential API.
+
+ * IP forwarding could cause memory leakage. This has been fixed.
+
+ ++ Other changes:
+
+ * Directory structure somewhat changed; the core/ tree has been
+ collapsed.
+
+(0.4.2) Changes since version 0.4.1
+
+ ++ New features:
+
+ * Experimental ARP implementation added.
+
+ * Skeleton Ethernet driver added.
+
+ * Experimental BSD socket API library added.
+
+ ++ Bugfixes:
+
+ * In very intense situations, memory leakage could occur. This has
+ been fixed.
+
+ ++ Other changes:
+
+ * Variables named "data" and "code" have been renamed in order to
+ avoid name conflicts in certain compilers.
+
+ * Variable++ have in appliciable cases been translated to ++variable
+ since some compilers generate better code in the latter case.
+
+(0.4.1) Changes since version 0.4
+
+ ++ New features:
+
+ * TCP: Connection attempts time out earlier than data
+ transmissions. Nagle algorithm implemented. Push flag set on the
+ last segment in a burst.
+
+ * UDP: experimental support for UDP-Lite extensions.
+
+ ++ Bugfixes:
+
+ * TCP: out of order segments were in some cases handled incorrectly,
+ and this has now been fixed. Delayed acknowledgements was broken
+ in 0.4, has now been fixed. Binding to an address that is in use
+ now results in an error. Reset connections sometimes hung an
+ application; this has been fixed.
+
+ * Checksum calculation sometimes failed for chained pbufs with odd
+ lengths. This has been fixed.
+
+ * API: a lot of bug fixes in the API. The UDP API has been improved
+ and tested. Error reporting and handling has been
+ improved. Logical flaws and race conditions for incoming TCP
+ connections has been found and removed.
+
+ * Memory manager: alignment issues. Reallocating memory sometimes
+ failed, this has been fixed.
+
+ * Generic library: bcopy was flawed and has been fixed.
+
+ ++ Other changes:
+
+ * API: all datatypes has been changed from generic ones such as
+ ints, to specified ones such as u16_t. Functions that return
+ errors now have the correct type (err_t).
+
+ * General: A lot of code cleaned up and debugging code removed. Many
+ portability issues have been fixed.
+
+ * The license was changed; the advertising clause was removed.
+
+ * C64 port added.
+
+ * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri
+ Kosunen, Mikael Caleres, and Frits Wilmink for reporting and
+ fixing bugs!
+
+(0.4) Changes since version 0.3.1
+
+ * Memory management has been radically changed; instead of
+ allocating memory from a shared heap, memory for objects that are
+ rapidly allocated and deallocated is now kept in pools. Allocation
+ and deallocation from those memory pools is very fast. The shared
+ heap is still present but is used less frequently.
+
+ * The memory, memory pool, and packet buffer subsystems now support
+ 4-, 2-, or 1-byte alignment.
+
+ * "Out of memory" situations are handled in a more robust way.
+
+ * Stack usage has been reduced.
+
+ * Easier configuration of lwIP parameters such as memory usage,
+ TTLs, statistics gathering, etc. All configuration parameters are
+ now kept in a single header file "lwipopts.h".
+
+ * The directory structure has been changed slightly so that all
+ architecture specific files are kept under the src/arch
+ hierarchy.
+
+ * Error propagation has been improved, both in the protocol modules
+ and in the API.
+
+ * The code for the RTXC architecture has been implemented, tested
+ and put to use.
+
+ * Bugs have been found and corrected in the TCP, UDP, IP, API, and
+ the Internet checksum modules.
+
+ * Bugs related to porting between a 32-bit and a 16-bit architecture
+ have been found and corrected.
+
+ * The license has been changed slightly to conform more with the
+ original BSD license, including the advertisement clause.
+
+(0.3.1) Changes since version 0.3
+
+ * Fix of a fatal bug in the buffer management. Pbufs with allocated
+ RAM never returned the RAM when the pbuf was deallocated.
+
+ * TCP congestion control, window updates and retransmissions did not
+ work correctly. This has now been fixed.
+
+ * Bugfixes in the API.
+
+(0.3) Changes since version 0.2
+
+ * New and improved directory structure. All include files are now
+ kept in a dedicated include/ directory.
+
+ * The API now has proper error handling. A new function,
+ netconn_err(), now returns an error code for the connection in
+ case of errors.
+
+ * Improvements in the memory management subsystem. The system now
+ keeps a pointer to the lowest free memory block. A new function,
+ mem_malloc2() tries to allocate memory once, and if it fails tries
+ to free some memory and retry the allocation.
+
+ * Much testing has been done with limited memory
+ configurations. lwIP now does a better job when overloaded.
+
+ * Some bugfixes and improvements to the buffer (pbuf) subsystem.
+
+ * Many bugfixes in the TCP code:
+
+ - Fixed a bug in tcp_close().
+
+ - The TCP receive window was incorrectly closed when out of
+ sequence segments was received. This has been fixed.
+
+ - Connections are now timed-out of the FIN-WAIT-2 state.
+
+ - The initial congestion window could in some cases be too
+ large. This has been fixed.
+
+ - The retransmission queue could in some cases be screwed up. This
+ has been fixed.
+
+ - TCP RST flag now handled correctly.
+
+ - Out of sequence data was in some cases never delivered to the
+ application. This has been fixed.
+
+ - Retransmitted segments now contain the correct acknowledgment
+ number and advertised window.
+
+ - TCP retransmission timeout backoffs are not correctly computed
+ (ala BSD). After a number of retransmissions, TCP now gives up
+ the connection.
+
+ * TCP connections now are kept on three lists, one for active
+ connections, one for listening connections, and one for
+ connections that are in TIME-WAIT. This greatly speeds up the fast
+ timeout processing for sending delayed ACKs.
+
+ * TCP now provides proper feedback to the application when a
+ connection has been successfully set up.
+
+ * More comments have been added to the code. The code has also been
+ somewhat cleaned up.
+
+(0.2) Initial public release.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..e3016d6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,29 @@
+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.
+
+
diff --git a/FILES b/FILES
new file mode 100644
index 0000000..1cef7db
--- /dev/null
+++ b/FILES
@@ -0,0 +1,5 @@
+src/ - The source code for the lwIP TCP/IP stack.
+
+proj/ - Makefiles and code for compiling lwIP.
+
+See also the FILES file in each subdirectory.
\ No newline at end of file
diff --git a/doc/rawapi.txt b/doc/rawapi.txt
new file mode 100644
index 0000000..fe8680f
--- /dev/null
+++ b/doc/rawapi.txt
@@ -0,0 +1,289 @@
+Raw TCP/IP interface for lwIP 0.5
+
+Author: Adam Dunkels
+
+$Id: rawapi.txt,v 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.
\ No newline at end of file
diff --git a/doc/sys_arch.txt b/doc/sys_arch.txt
new file mode 100644
index 0000000..841d127
--- /dev/null
+++ b/doc/sys_arch.txt
@@ -0,0 +1,125 @@
+sys_arch interface for lwIP 0.5
+
+Author: Adam Dunkels
+
+$Id: sys_arch.txt,v 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.
+
diff --git a/proj/minimal/Makefile b/proj/minimal/Makefile
new file mode 100644
index 0000000..6c2033d
--- /dev/null
+++ b/proj/minimal/Makefile
@@ -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 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)
+
+
diff --git a/proj/minimal/README b/proj/minimal/README
new file mode 100644
index 0000000..0edb5f7
--- /dev/null
+++ b/proj/minimal/README
@@ -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.
\ No newline at end of file
diff --git a/proj/minimal/echo.c b/proj/minimal/echo.c
new file mode 100644
index 0000000..652208e
--- /dev/null
+++ b/proj/minimal/echo.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
+
diff --git a/proj/minimal/lwipopts.h b/proj/minimal/lwipopts.h
new file mode 100644
index 0000000..85e304d
--- /dev/null
+++ b/proj/minimal/lwipopts.h
@@ -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__ */
diff --git a/proj/minimal/main.c b/proj/minimal/main.c
new file mode 100644
index 0000000..0a6e1a8
--- /dev/null
+++ b/proj/minimal/main.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
diff --git a/proj/minimal/mintapif.c b/proj/minimal/mintapif.c
new file mode 100644
index 0000000..38cad39
--- /dev/null
+++ b/proj/minimal/mintapif.c
@@ -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;
+}
diff --git a/proj/minimal/mintapif.h b/proj/minimal/mintapif.h
new file mode 100644
index 0000000..7203167
--- /dev/null
+++ b/proj/minimal/mintapif.h
@@ -0,0 +1,45 @@
+/*
+ * 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 __MINTAPIF_H__
+#define __MINTAPIF_H__
+
+#include "lwip/netif.h"
+
+enum mintapif_signal {
+ MINTAPIF_TIMEOUT,
+ MINTAPIF_PACKET
+};
+
+void mintapif_init(struct netif *netif);
+enum mintapif_signal mintapif_wait(struct netif *netif, u16_t time);
+
+#endif /* __MINTAPIF_H__ */
diff --git a/proj/unixsim/Makefile b/proj/unixsim/Makefile
new file mode 100644
index 0000000..341f7c0
--- /dev/null
+++ b/proj/unixsim/Makefile
@@ -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 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)
+
diff --git a/proj/unixsim/README b/proj/unixsim/README
new file mode 100644
index 0000000..c212578
--- /dev/null
+++ b/proj/unixsim/README
@@ -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/.
+
diff --git a/proj/unixsim/apps/fs.c b/proj/unixsim/apps/fs.c
new file mode 100644
index 0000000..3c74112
--- /dev/null
+++ b/proj/unixsim/apps/fs.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/proj/unixsim/apps/fs.h b/proj/unixsim/apps/fs.h
new file mode 100644
index 0000000..e6a1d63
--- /dev/null
+++ b/proj/unixsim/apps/fs.h
@@ -0,0 +1,44 @@
+/*
+ * 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 __FS_H__
+#define __FS_H__
+
+struct fs_file {
+ char *data;
+ int len;
+};
+
+/* file must be allocated by caller and will be filled in
+ by the function. */
+int fs_open(char *name, struct fs_file *file);
+
+#endif /* __FS_H__ */
diff --git a/proj/unixsim/apps/fs/documentation.html b/proj/unixsim/apps/fs/documentation.html
new file mode 100644
index 0000000..baf3580
--- /dev/null
+++ b/proj/unixsim/apps/fs/documentation.html
@@ -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">
+
+</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
+<adam@sics.se></a>.
+</p>
+
+
+<p align="right">
+<font size="-1"><i>
+$Date: 2002/10/19 13:00:01 $
+</i></font>
+</p>
+
+
+</td>
+<td width="50">
+
+</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>
diff --git a/proj/unixsim/apps/fs/download.html b/proj/unixsim/apps/fs/download.html
new file mode 100644
index 0000000..59d7cf5
--- /dev/null
+++ b/proj/unixsim/apps/fs/download.html
@@ -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">
+
+</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">
+
+</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>
diff --git a/proj/unixsim/apps/fs/img/sics.gif b/proj/unixsim/apps/fs/img/sics.gif
new file mode 100644
index 0000000..0a4fc7b
--- /dev/null
+++ b/proj/unixsim/apps/fs/img/sics.gif
Binary files differ
diff --git a/proj/unixsim/apps/fs/licence.html b/proj/unixsim/apps/fs/licence.html
new file mode 100644
index 0000000..40f0597
--- /dev/null
+++ b/proj/unixsim/apps/fs/licence.html
@@ -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">
+
+</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">
+
+</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>
diff --git a/proj/unixsim/apps/fs/links.html b/proj/unixsim/apps/fs/links.html
new file mode 100644
index 0000000..2dfa0f9
--- /dev/null
+++ b/proj/unixsim/apps/fs/links.html
@@ -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">
+
+</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">
+
+</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>
diff --git a/proj/unixsim/apps/fs/mailinglist.html b/proj/unixsim/apps/fs/mailinglist.html
new file mode 100644
index 0000000..1cd8914
--- /dev/null
+++ b/proj/unixsim/apps/fs/mailinglist.html
@@ -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">
+
+</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">
+
+</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>
diff --git a/proj/unixsim/apps/fs/os.html b/proj/unixsim/apps/fs/os.html
new file mode 100644
index 0000000..6d66b82
--- /dev/null
+++ b/proj/unixsim/apps/fs/os.html
@@ -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">
+
+</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">
+
+</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>
diff --git a/proj/unixsim/apps/fs/os.png b/proj/unixsim/apps/fs/os.png
new file mode 100644
index 0000000..deea8f2
--- /dev/null
+++ b/proj/unixsim/apps/fs/os.png
Binary files differ
diff --git a/proj/unixsim/apps/fs/threads.png b/proj/unixsim/apps/fs/threads.png
new file mode 100644
index 0000000..2486ab4
--- /dev/null
+++ b/proj/unixsim/apps/fs/threads.png
Binary files differ
diff --git a/proj/unixsim/apps/fsdata.c b/proj/unixsim/apps/fsdata.c
new file mode 100644
index 0000000..4ffaed5
--- /dev/null
+++ b/proj/unixsim/apps/fsdata.c
@@ -0,0 +1,4188 @@
+static const char data_404_html[] = {
+ /* /404.html */
+ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 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, 0xd, 0xa, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x2f, 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20,
+ 0x28, 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, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x3c, 0x62,
+ 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e,
+ 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x30, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c,
+ 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x54, 0x72, 0x79, 0x20, 0x61, 0x6e,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, 0x65,
+ 0x2e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, };
+
+static const char data_mailinglist_html[] = {
+ /* /mailinglist.html */
+ 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x4d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c,
+ 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68,
+ 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x62, 0x6f,
+ 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e, 0xa,
+ 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22,
+ 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69,
+ 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c,
+ 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa,
+ 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e,
+ 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69,
+ 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x5b, 0x4d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x5d,
+ 0xa, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32,
+ 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x2f,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65,
+ 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d,
+ 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e,
+ 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22, 0x3e,
+ 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69,
+ 0x74, 0x65, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x35, 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa, 0xa, 0x3c,
+ 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a,
+ 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54,
+ 0x68, 0x65, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x6d, 0x61,
+ 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x73,
+ 0x63, 0x75, 0x73, 0x73, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2e,
+ 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63,
+ 0x73, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0xa,
+ 0x74, 0x6f, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2c, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x70, 0x6f, 0x72,
+ 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2c, 0x20,
+ 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65,
+ 0x76, 0x69, 0x63, 0x65, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65,
+ 0x72, 0x73, 0x20, 0x6f, 0x72, 0xa, 0x61, 0x70, 0x70, 0x6c,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x63, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x75, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0xa, 0x3c,
+ 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x41,
+ 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x73, 0x3c, 0x2f, 0x68,
+ 0x33, 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67,
+ 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79,
+ 0x22, 0x3e, 0xa, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
+ 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x6c, 0x69,
+ 0x73, 0x74, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa,
+ 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x53, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x62, 0x65, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa,
+ 0x54, 0x6f, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
+ 0x62, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x3c,
+ 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61,
+ 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+ 0x64, 0x6f, 0x6d, 0x6f, 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e,
+ 0x73, 0x65, 0x22, 0x3e, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x64,
+ 0x6f, 0x6d, 0x6f, 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73,
+ 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0xa, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x73,
+ 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x6c,
+ 0x77, 0x69, 0x70, 0xa, 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65,
+ 0x3e, 0xa, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x62, 0x6f, 0x64,
+ 0x79, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x75, 0x62,
+ 0x6a, 0x65, 0x63, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c,
+ 0x64, 0x20, 0x62, 0x65, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x20,
+ 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x2e, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x49, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x65, 0x77,
+ 0x20, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x2c, 0x20,
+ 0x79, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x61,
+ 0x20, 0x77, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x6f, 0x6d, 0x65, 0xa, 0x69, 0x6e, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65,
+ 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c,
+ 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x73, 0x74,
+ 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66,
+ 0x6f, 0x72, 0xa, 0x75, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x62, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x53, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x72,
+ 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x20,
+ 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73,
+ 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x59, 0x6f, 0x75,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61,
+ 0x6e, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x6d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20,
+ 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72,
+ 0x21, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68,
+ 0x33, 0x3e, 0x50, 0x6f, 0x73, 0x74, 0x3c, 0x2f, 0x68, 0x33,
+ 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x20, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20,
+ 0x6c, 0x69, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20,
+ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x73, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20,
+ 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0xa, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d,
+ 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a, 0x6c, 0x77, 0x69, 0x70,
+ 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x22, 0x3e,
+ 0x6c, 0x77, 0x69, 0x70, 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e,
+ 0x73, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa, 0x3c, 0x2f,
+ 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x55, 0x6e,
+ 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x3c,
+ 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69,
+ 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54, 0x6f, 0x20, 0x73, 0x75,
+ 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2c, 0x20, 0x73,
+ 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x69, 0x6c,
+ 0x20, 0x74, 0x6f, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x74, 0x6f, 0x3a,
+ 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x64, 0x6f, 0x6d, 0x6f, 0x40,
+ 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x22, 0x3e, 0x6d,
+ 0x61, 0x6a, 0x6f, 0x72, 0x64, 0x6f, 0x6d, 0x6f, 0x40, 0x73,
+ 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0xa, 0x3c, 0x70,
+ 0x72, 0x65, 0x3e, 0xa, 0x75, 0x6e, 0x73, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x6c, 0x77, 0x69, 0x70,
+ 0xa, 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63,
+ 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x20, 0x62, 0x6c, 0x61,
+ 0x6e, 0x6b, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, 0x6e,
+ 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x31,
+ 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, 0x74,
+ 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x31, 0x2f, 0x31, 0x32,
+ 0x2f, 0x31, 0x32, 0x20, 0x31, 0x35, 0x3a, 0x34, 0x38, 0x3a,
+ 0x35, 0x37, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, 0x3c,
+ 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22,
+ 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x68,
+ 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x6e,
+ 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65,
+ 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e,
+ 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x5b, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0xa, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f,
+ 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c,
+ 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69, 0x6e, 0x6b,
+ 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x72,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0xa, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d,
+ 0x2f, 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75,
+ 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f,
+ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3e, 0xa, };
+
+static const char data_links_html[] = {
+ /* /links.html */
+ 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x4c, 0x69, 0x6e,
+ 0x6b, 0x73, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
+ 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0xa,
+ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
+ 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa,
+ 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c,
+ 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61,
+ 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c,
+ 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f,
+ 0x67, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x5b, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x5d, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32, 0x3e,
+ 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e,
+ 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30,
+ 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77,
+ 0x68, 0x69, 0x74, 0x65, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0xa, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x70, 0x61, 0x67,
+ 0x65, 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c,
+ 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
+ 0x77, 0x77, 0x2e, 0x65, 0x73, 0x72, 0x61, 0x63, 0x2e, 0x65,
+ 0x6c, 0x65, 0x2e, 0x74, 0x75, 0x65, 0x2e, 0x6e, 0x6c, 0x2f,
+ 0x7e, 0x6c, 0x65, 0x6f, 0x6e, 0x2f, 0x6c, 0x77, 0x69, 0x70,
+ 0x2f, 0x22, 0x3e, 0x4c, 0x65, 0x6f, 0x6e, 0x20, 0x57, 0x6f,
+ 0x65, 0x73, 0x74, 0x65, 0x6e, 0x62, 0x65, 0x72, 0x67, 0x27,
+ 0x73, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x70, 0x61, 0x67,
+ 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c, 0x2f, 0x75, 0x6c,
+ 0x3e, 0xa, 0xa, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x69,
+ 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x77, 0x49, 0x50, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x69, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
+ 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x55, 0x4b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64,
+ 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x74, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x74, 0x64, 0x65,
+ 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x2e, 0x75,
+ 0x6b, 0x2f, 0x22, 0x3e, 0x54, 0x61, 0x6e, 0x67, 0x65, 0x6e,
+ 0x74, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20,
+ 0x4c, 0x74, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x66, 0x69, 0x6c, 0x6d, 0xa, 0x61, 0x6e, 0x64, 0x20, 0x76,
+ 0x69, 0x64, 0x65, 0x6f, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x2d,
+ 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x65, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x78, 0x6f, 0x6e,
+ 0x2e, 0x74, 0x76, 0x22, 0x3e, 0x41, 0x78, 0x6f, 0x6e, 0x20,
+ 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x44, 0x65,
+ 0x73, 0x69, 0x67, 0x6e, 0x20, 0x42, 0x56, 0x3c, 0x2f, 0x61,
+ 0x3e, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x68, 0x65, 0xa, 0x4e,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x72, 0x67, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x49, 0x50, 0x20, 0x73,
+ 0x74, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0xa,
+ 0x53, 0x79, 0x6e, 0x61, 0x70, 0x73, 0x65, 0x20, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x72, 0x6f, 0x61,
+ 0x64, 0x63, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0xa, 0x3c, 0x2f, 0x75,
+ 0x6c, 0x3e, 0xa, 0xa, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x77, 0x49, 0x50, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x63, 0x64, 0x74, 0x2e, 0x6c, 0x75,
+ 0x74, 0x68, 0x2e, 0x73, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x6a,
+ 0x65, 0x63, 0x74, 0x73, 0x2f, 0x61, 0x72, 0x65, 0x6e, 0x61,
+ 0x2f, 0x22, 0x3e, 0x54, 0x68, 0x65, 0x20, 0x41, 0x52, 0x45,
+ 0x4e, 0x41, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x48, 0x6f, 0x63,
+ 0x6b, 0x65, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72,
+ 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x75, 0x6c, 0x73,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x6e, 0x73,
+ 0x6f, 0x72, 0x73, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2e, 0x3c, 0x62, 0x72,
+ 0x3e, 0x20, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x62, 0x61, 0x72, 0x74, 0x2e, 0x73, 0x6d,
+ 0x2e, 0x6c, 0x75, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x2f, 0x65,
+ 0x69, 0x73, 0x32, 0x30, 0x30, 0x31, 0x2f, 0x22, 0x3e, 0x54,
+ 0x68, 0x65, 0x20, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65,
+ 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
+ 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x32,
+ 0x30, 0x30, 0x31, 0x20, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e,
+ 0x74, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x46, 0x6c, 0x6f, 0x77,
+ 0x20, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x6c, 0x74, 0x20, 0x74, 0x65, 0x6e, 0x73,
+ 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72,
+ 0x73, 0xa, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20,
+ 0x6c, 0x77, 0x49, 0x50, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x64, 0x63, 0x64, 0x65, 0x76, 0x2e, 0x61, 0x6c, 0x6c, 0x75,
+ 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x22,
+ 0x3e, 0x4b, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d,
+ 0x20, 0x54, 0x68, 0x65, 0x20, 0x4b, 0x4f, 0x53, 0x20, 0x6f,
+ 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0xa,
+ 0x53, 0x65, 0x67, 0x61, 0x20, 0x44, 0x72, 0x65, 0x61, 0x6d,
+ 0x63, 0x61, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20,
+ 0x6c, 0x77, 0x49, 0x50, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa,
+ 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0xa, 0x4f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x54,
+ 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x69, 0x6d, 0x70, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x75,
+ 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22,
+ 0x3e, 0x75, 0x49, 0x50, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d,
+ 0x20, 0x41, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6d,
+ 0x61, 0x6c, 0x6c, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50,
+ 0x20, 0xa, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x73, 0x75,
+ 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x52, 0x41, 0x4d,
+ 0xa, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x66, 0x65, 0x77,
+ 0x20, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x79, 0x74, 0x65, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x63,
+ 0x6f, 0x64, 0x65, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e,
+ 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x75, 0x63, 0x69, 0x70, 0x2e,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x67,
+ 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x22, 0x3e, 0x75, 0x43,
+ 0x2f, 0x49, 0x50, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20,
+ 0x75, 0x43, 0x2f, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x42, 0x53, 0x44, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x64,
+ 0xa, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x73, 0x74, 0x61,
+ 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x69, 0x63,
+ 0x72, 0x6f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
+ 0x65, 0x72, 0x73, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c,
+ 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c,
+ 0x69, 0x71, 0x75, 0x6f, 0x72, 0x69, 0x63, 0x65, 0x2e, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x67, 0x65,
+ 0x2e, 0x6e, 0x65, 0x74, 0x22, 0x3e, 0x4c, 0x69, 0x71, 0x75,
+ 0x6f, 0x72, 0x69, 0x63, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x20,
+ 0x2d, 0x20, 0x4c, 0x69, 0x71, 0x75, 0x6f, 0x72, 0x69, 0x63,
+ 0x65, 0xa, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73,
+ 0x20, 0x61, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20,
+ 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x3c, 0x62, 0x72, 0x3e,
+ 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x65, 0x6e, 0x69, 0x65,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63, 0x70, 0x63, 0x69, 0x70,
+ 0x2f, 0x22, 0x3e, 0x43, 0x50, 0x43, 0x2f, 0x49, 0x50, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x41, 0x20, 0x54, 0x43,
+ 0x50, 0x2f, 0x49, 0x50, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b,
+ 0x20, 0x66, 0x6f, 0x72, 0xa, 0x41, 0x6d, 0x73, 0x74, 0x72,
+ 0x61, 0x64, 0x20, 0x43, 0x50, 0x43, 0x73, 0x2e, 0x3c, 0x62,
+ 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x6c, 0x6e, 0x67, 0x2e, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x6e,
+ 0x65, 0x74, 0x2f, 0x22, 0x3e, 0x4c, 0x55, 0x6e, 0x69, 0x78,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x4c, 0x55, 0x6e,
+ 0x69, 0x78, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+ 0x73, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xa,
+ 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x73, 0x74, 0x61,
+ 0x63, 0x6b, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,
+ 0x77, 0x2e, 0x73, 0x77, 0x65, 0x65, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x72, 0x69, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a,
+ 0x6f, 0x6c, 0x7a, 0x36, 0x34, 0x2f, 0x6a, 0x6f, 0x73, 0x2f,
+ 0x22, 0x3e, 0x4a, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e, 0x20,
+ 0x2d, 0x20, 0x4a, 0x4f, 0x53, 0x20, 0x69, 0x6e, 0x63, 0x6c,
+ 0x75, 0x64, 0x65, 0x73, 0x20, 0x61, 0xa, 0x54, 0x43, 0x50,
+ 0x2f, 0x49, 0x50, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x73,
+ 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74,
+ 0x2f, 0x62, 0x70, 0x61, 0x64, 0x64, 0x6f, 0x63, 0x6b, 0x2f,
+ 0x74, 0x69, 0x6e, 0x79, 0x74, 0x63, 0x70, 0x2f, 0x64, 0x65,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x22,
+ 0x3e, 0x54, 0x69, 0x6e, 0x79, 0x54, 0x43, 0x50, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x41, 0x20, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x73, 0x6c, 0x69, 0x6d, 0xa, 0x54, 0x43, 0x50,
+ 0x2c, 0x20, 0x49, 0x50, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x46, 0x54, 0x50, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x6b, 0x79, 0x6c, 0x6c, 0x69, 0x6b,
+ 0x6b, 0x69, 0x2e, 0x66, 0x6c, 0x75, 0x66, 0x66, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72,
+ 0x65, 0x2f, 0x77, 0x77, 0x77, 0x70, 0x69, 0x63, 0x32, 0x2f,
+ 0x22, 0x3e, 0x57, 0x57, 0x57, 0x70, 0x69, 0x63, 0x32, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x53, 0x6d, 0x61, 0x6c,
+ 0x6c, 0xa, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x54, 0x43, 0x50,
+ 0x2f, 0x49, 0x50, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x50, 0x49, 0x43, 0x2e, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x6d,
+ 0x62, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x2e, 0x66, 0x73, 0x6e,
+ 0x65, 0x74, 0x2e, 0x63, 0x6f, 0x2e, 0x75, 0x6b, 0x2f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x2f,
+ 0x70, 0x69, 0x63, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f,
+ 0x70, 0x69, 0x63, 0x73, 0x65, 0x72, 0x76, 0x64, 0x2e, 0x68,
+ 0x74, 0x6d, 0x22, 0x3e, 0x50, 0x49, 0x43, 0x20, 0x57, 0x65,
+ 0x62, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x53, 0x6d, 0x61, 0x6c, 0x6c,
+ 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x54, 0x43, 0x50, 0x2f,
+ 0x49, 0x50, 0x2f, 0x53, 0x4c, 0x49, 0x50, 0x20, 0x50, 0x49,
+ 0x43, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x3c, 0x62, 0x72,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0xa, 0x56,
+ 0x65, 0x72, 0x79, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20,
+ 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x6f,
+ 0x72, 0x6c, 0x64, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x7e, 0x66, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2f,
+ 0x61, 0x63, 0x65, 0x2f, 0x22, 0x3e, 0x77, 0x65, 0x62, 0x41,
+ 0x43, 0x45, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d, 0x20, 0x57,
+ 0x6f, 0x72, 0x6c, 0x64, 0x27, 0x73, 0x20, 0x53, 0x6d, 0x61,
+ 0x6c, 0x6c, 0x65, 0x73, 0x74, 0xa, 0x57, 0x65, 0x62, 0x20,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x3c, 0x62, 0x72,
+ 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2d, 0x63, 0x63, 0x73, 0x2e,
+ 0x63, 0x73, 0x2e, 0x75, 0x6d, 0x61, 0x73, 0x73, 0x2e, 0x65,
+ 0x64, 0x75, 0x2f, 0x7e, 0x73, 0x68, 0x72, 0x69, 0x2f, 0x69,
+ 0x50, 0x69, 0x63, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x69, 0x50, 0x49, 0x43, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x2d,
+ 0x20, 0x41, 0x20, 0x4d, 0x61, 0x74, 0x63, 0x68, 0xa, 0x48,
+ 0x65, 0x61, 0x64, 0x20, 0x53, 0x69, 0x7a, 0x65, 0x64, 0x20,
+ 0x57, 0x65, 0x62, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x75, 0x6c,
+ 0x3e, 0xa, 0xa, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x52, 0x46, 0x43, 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c,
+ 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x4a, 0x2e, 0x20, 0x50,
+ 0x6f, 0x73, 0x74, 0x65, 0x6c, 0x2c, 0x20, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72,
+ 0x66, 0x63, 0x37, 0x39, 0x31, 0x2e, 0x74, 0x78, 0x74, 0x22,
+ 0x3e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x37, 0x39, 0x31,
+ 0x2c, 0x20, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65,
+ 0x72, 0x20, 0x31, 0x39, 0x38, 0x31, 0x2e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x4a, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x65,
+ 0x6c, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x74,
+ 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67,
+ 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x37, 0x39,
+ 0x32, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+ 0x72, 0x6f, 0x6c, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x37,
+ 0x39, 0x32, 0x2c, 0x20, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
+ 0x62, 0x65, 0x72, 0x20, 0x31, 0x39, 0x38, 0x31, 0x2e, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x4a, 0x2e, 0x20, 0x50, 0x6f, 0x73,
+ 0x74, 0x65, 0x6c, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63,
+ 0x37, 0x36, 0x38, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x55,
+ 0x73, 0x65, 0x72, 0x20, 0x44, 0x61, 0x74, 0x61, 0x67, 0x72,
+ 0x61, 0x6d, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
+ 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43,
+ 0x37, 0x36, 0x38, 0x2c, 0x20, 0x41, 0x75, 0x67, 0x75, 0x73,
+ 0x74, 0x20, 0x31, 0x39, 0x38, 0x30, 0x2e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x4a, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x74, 0x65,
+ 0x6c, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x74,
+ 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67,
+ 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x37, 0x39,
+ 0x33, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x61,
+ 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+ 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2c, 0x20, 0x52, 0x46, 0x43, 0x37, 0x39, 0x33, 0x2c, 0x20,
+ 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20,
+ 0x31, 0x39, 0x38, 0x31, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e,
+ 0x44, 0x2e, 0x20, 0x44, 0x2e, 0x20, 0x43, 0x6c, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x74,
+ 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67,
+ 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x38, 0x31,
+ 0x33, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x57, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x63,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
+ 0x67, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x43, 0x50, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x38, 0x31,
+ 0x33, 0x2c, 0x20, 0x4a, 0x75, 0x6c, 0x79, 0x20, 0x31, 0x39,
+ 0x38, 0x32, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x44, 0x2e,
+ 0x20, 0x44, 0x2e, 0x20, 0x43, 0x6c, 0x61, 0x72, 0x6b, 0x2c,
+ 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e,
+ 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72,
+ 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x38, 0x31, 0x37, 0x2e,
+ 0x74, 0x78, 0x74, 0x22, 0x3e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x61, 0x72, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x45, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x79,
+ 0x20, 0x69, 0x6e, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
+ 0x6f, 0x6c, 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61,
+ 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x38, 0x31, 0x37, 0x2c,
+ 0x20, 0x4a, 0x75, 0x6c, 0x79, 0x20, 0x31, 0x39, 0x38, 0x32,
+ 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x52, 0x2e, 0x20, 0x42,
+ 0x72, 0x61, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72,
+ 0x66, 0x63, 0x31, 0x31, 0x32, 0x32, 0x2e, 0x74, 0x78, 0x74,
+ 0x22, 0x3e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x48, 0x6f,
+ 0x73, 0x74, 0x73, 0x20, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x3c, 0x2f, 0x61,
+ 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x31, 0x31, 0x32, 0x32,
+ 0x2c, 0x20, 0x4f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x20,
+ 0x31, 0x39, 0x38, 0x39, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e,
+ 0x54, 0x2e, 0x20, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x72, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x2e, 0x20, 0x4b, 0x75,
+ 0x6c, 0x6c, 0x62, 0x65, 0x72, 0x67, 0x2c, 0x20, 0x3c, 0x61,
+ 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74,
+ 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f,
+ 0x72, 0x66, 0x63, 0x31, 0x31, 0x34, 0x31, 0x2e, 0x74, 0x78,
+ 0x74, 0x22, 0x3e, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x31, 0x31, 0x34,
+ 0x31, 0x2c, 0x20, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x79,
+ 0x20, 0x31, 0x39, 0x39, 0x30, 0x2e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x41, 0x2e, 0x20, 0x52, 0x69, 0x6a, 0x73, 0x69, 0x6e,
+ 0x67, 0x68, 0x61, 0x6e, 0x69, 0x2c, 0x20, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72,
+ 0x66, 0x63, 0x31, 0x36, 0x32, 0x34, 0x2e, 0x74, 0x78, 0x74,
+ 0x22, 0x3e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x76,
+ 0x69, 0x61, 0x20, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74,
+ 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43,
+ 0x31, 0x36, 0x32, 0x34, 0x2c, 0x20, 0x4d, 0x61, 0x79, 0x20,
+ 0x31, 0x39, 0x39, 0x34, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e,
+ 0x52, 0x2e, 0x20, 0x42, 0x72, 0x61, 0x64, 0x65, 0x6e, 0x2c,
+ 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e,
+ 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72,
+ 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x31, 0x33, 0x33, 0x37,
+ 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x54, 0x49, 0x4d, 0x45,
+ 0x2d, 0x57, 0x41, 0x49, 0x54, 0x20, 0x41, 0x73, 0x73, 0x61,
+ 0x73, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x48,
+ 0x61, 0x7a, 0x61, 0x72, 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x54, 0x43, 0x50, 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52,
+ 0x46, 0x43, 0x31, 0x33, 0x33, 0x37, 0x2c, 0x20, 0x4d, 0x61,
+ 0x79, 0x20, 0x31, 0x39, 0x39, 0x32, 0x2e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x42, 0x2e, 0x20, 0x43, 0x61, 0x72, 0x70, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
+ 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66,
+ 0x63, 0x31, 0x39, 0x35, 0x38, 0x2e, 0x74, 0x78, 0x74, 0x22,
+ 0x3e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74,
+ 0x75, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x72, 0x69, 0x6e, 0x63,
+ 0x69, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43,
+ 0x31, 0x39, 0x35, 0x38, 0x2c, 0x20, 0x4a, 0x75, 0x6e, 0x65,
+ 0x20, 0x31, 0x39, 0x39, 0x36, 0x2e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x4d, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x56, 0x2e, 0x20, 0x50, 0x61, 0x78, 0x73, 0x6f,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x57, 0x2e, 0x20, 0x53,
+ 0x74, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x3c, 0x61,
+ 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x66, 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74,
+ 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f,
+ 0x72, 0x66, 0x63, 0x32, 0x35, 0x38, 0x31, 0x2e, 0x74, 0x78,
+ 0x74, 0x22, 0x3e, 0x54, 0x43, 0x50, 0x20, 0x43, 0x6f, 0x6e,
+ 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f,
+ 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x2c,
+ 0x20, 0x52, 0x46, 0x43, 0x32, 0x35, 0x38, 0x31, 0x2c, 0x20,
+ 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x31, 0x39, 0x39, 0x39,
+ 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x53, 0x2e, 0x20, 0x50,
+ 0x61, 0x72, 0x6b, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x43, 0x2e, 0x20, 0x53, 0x63, 0x68, 0x6d, 0x65, 0x63, 0x68,
+ 0x65, 0x6c, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x66, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66,
+ 0x74, 0x70, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x72, 0x66, 0x63, 0x2f, 0x72, 0x66, 0x63, 0x32,
+ 0x33, 0x39, 0x38, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x53,
+ 0x6f, 0x6d, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x54, 0x43, 0x50, 0x20, 0x49, 0x6d, 0x70, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x2c, 0x20, 0x52, 0x46, 0x43, 0x32, 0x33, 0x39,
+ 0x38, 0x2c, 0x20, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x20,
+ 0x31, 0x39, 0x39, 0x38, 0x2e, 0xa, 0x3c, 0x2f, 0x75, 0x6c,
+ 0x3e, 0xa, 0xa, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x56, 0x2e, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x43, 0x6f, 0x6e,
+ 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76,
+ 0x6f, 0x69, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e,
+ 0x20, 0x49, 0x6e, 0x20, 0x3c, 0x69, 0x3e, 0x50, 0x72, 0x6f,
+ 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f,
+ 0x66, 0xa, 0x74, 0x68, 0x65, 0x20, 0x53, 0x49, 0x47, 0x43,
+ 0x4f, 0x4d, 0x4d, 0x20, 0x27, 0x38, 0x38, 0x20, 0x43, 0x6f,
+ 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f,
+ 0x69, 0x3e, 0x2c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x66, 0x6f,
+ 0x72, 0x64, 0x2c, 0x20, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x2c, 0x20, 0x41, 0x75, 0x67, 0x75,
+ 0x73, 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x2e, 0xa, 0x3c,
+ 0x6c, 0x69, 0x3e, 0x56, 0x2e, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x34, 0x2e, 0x33, 0x42,
+ 0x53, 0x44, 0x20, 0x54, 0x43, 0x50, 0x20, 0x68, 0x65, 0x61,
+ 0x64, 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x3c, 0x69, 0x3e, 0x41,
+ 0x43, 0x4d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65,
+ 0x72, 0xa, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x52, 0x65, 0x76,
+ 0x69, 0x65, 0x77, 0x3c, 0x2f, 0x69, 0x3e, 0x2c, 0x20, 0x32,
+ 0x30, 0x28, 0x32, 0x29, 0x2c, 0x20, 0x41, 0x70, 0x72, 0x69,
+ 0x6c, 0x20, 0x31, 0x39, 0x39, 0x30, 0x2e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x50, 0x2e, 0x20, 0x4b, 0x61, 0x72, 0x6e, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x43, 0x2e, 0x20, 0x50, 0x61, 0x72,
+ 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2e, 0x20, 0x49, 0x6d,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x74, 0x72, 0x69, 0x70, 0x20, 0x74,
+ 0x69, 0x6d, 0x65, 0x20, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
+ 0x74, 0x65, 0x73, 0xa, 0x69, 0x6e, 0x20, 0x72, 0x65, 0x6c,
+ 0x69, 0x61, 0x62, 0x6c, 0x69, 0x65, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x2e, 0x20, 0x49, 0x6e,
+ 0x20, 0x3c, 0x69, 0x3e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x65,
+ 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x53, 0x49, 0x47, 0x43, 0x4f, 0x4d, 0x4d,
+ 0x20, 0x27, 0x38, 0x37, 0xa, 0x43, 0x6f, 0x6e, 0x66, 0x65,
+ 0x72, 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f, 0x69, 0x3e, 0x2c,
+ 0x20, 0x53, 0x74, 0x6f, 0x77, 0x65, 0x2c, 0x20, 0x56, 0x65,
+ 0x72, 0x6d, 0x6f, 0x6e, 0x74, 0x2c, 0x20, 0x41, 0x75, 0x67,
+ 0x75, 0x73, 0x74, 0x20, 0x31, 0x39, 0x38, 0x37, 0x2e, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x4a, 0x2e, 0x20, 0x4b, 0x61, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x2e, 0x20, 0x50, 0x61,
+ 0x73, 0x71, 0x75, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x50, 0x72,
+ 0x6f, 0x66, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x52, 0x65, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67,
+ 0x20, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
+ 0x67, 0xa, 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x61, 0x64,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49,
+ 0x50, 0x2e, 0x20, 0x3c, 0x69, 0x3e, 0x49, 0x45, 0x45, 0x45,
+ 0x2f, 0x41, 0x43, 0x4d, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e,
+ 0x67, 0x3c, 0x2f, 0x69, 0x3e, 0x2c, 0x20, 0x34, 0x28, 0x36,
+ 0x29, 0x2c, 0x20, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65,
+ 0x72, 0x20, 0x31, 0x39, 0x39, 0x36, 0x2e, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x4c, 0x2e, 0x20, 0x4c, 0x61, 0x72, 0x7a, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x4d, 0x2e, 0x20, 0x44, 0x65, 0x67, 0x65,
+ 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x53, 0x2e, 0x20, 0x50, 0x69, 0x6e, 0x6b, 0x2e, 0x20,
+ 0x55, 0x44, 0x50, 0x20, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0xa, 0x72, 0x65, 0x61, 0x6c, 0x2d, 0x74, 0x69,
+ 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x65,
+ 0x64, 0x69, 0x61, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x49, 0x6e,
+ 0x20, 0x3c, 0x69, 0x3e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x65,
+ 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x49, 0x45, 0x45, 0x45, 0xa, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61,
+ 0x6c, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x3c, 0x2f, 0x69, 0x3e, 0x2c, 0x20, 0x56, 0x61, 0x6e, 0x63,
+ 0x6f, 0x75, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x72, 0x69,
+ 0x74, 0x69, 0x73, 0x68, 0xa, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+ 0x62, 0x69, 0x61, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64,
+ 0x61, 0x2c, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x31, 0x39,
+ 0x39, 0x39, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x50, 0x2e,
+ 0x20, 0x45, 0x2e, 0x20, 0x4d, 0x63, 0x4b, 0x65, 0x6e, 0x6e,
+ 0x65, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x2e, 0x20,
+ 0x46, 0x2e, 0x20, 0x44, 0x6f, 0x76, 0x65, 0x2e, 0x20, 0x45,
+ 0x66, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x6d,
+ 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e,
+ 0x67, 0x20, 0x6f, 0x66, 0xa, 0x69, 0x6e, 0x63, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x67, 0x20, 0x54, 0x43, 0x50, 0x20, 0x70, 0x61,
+ 0x63, 0x6b, 0x65, 0x74, 0x73, 0x2e, 0x20, 0x49, 0x6e, 0x20,
+ 0x3c, 0x69, 0x3e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x65, 0x64,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x53, 0x49, 0x47, 0x43, 0x4f, 0x4d, 0x4d, 0x20,
+ 0x27, 0x39, 0x32, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x65, 0x72,
+ 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f, 0x69, 0x3e, 0x2c, 0x20,
+ 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x2c,
+ 0x20, 0x4d, 0x61, 0x72, 0x79, 0x6c, 0x61, 0x6e, 0x64, 0x2c,
+ 0x20, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x20, 0x31, 0x39,
+ 0x39, 0x32, 0x2e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x43, 0x2e,
+ 0x20, 0x50, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x2e, 0x20, 0x50, 0x69,
+ 0x6e, 0x6b, 0x2e, 0x20, 0x41, 0x20, 0x66, 0x61, 0x73, 0x74,
+ 0x65, 0x72, 0x20, 0x55, 0x44, 0x50, 0x2e, 0x20, 0x3c, 0x69,
+ 0x3e, 0x49, 0x45, 0x45, 0x45, 0x2f, 0x41, 0x43, 0x4d, 0x20,
+ 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0xa, 0x69, 0x6e, 0x20, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x3c, 0x2f, 0x69, 0x3e,
+ 0x2c, 0x20, 0x31, 0x28, 0x34, 0x29, 0x2c, 0x20, 0x41, 0x75,
+ 0x67, 0x75, 0x73, 0x74, 0x20, 0x31, 0x39, 0x39, 0x33, 0x2e,
+ 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0xa, 0xa, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, 0x6e,
+ 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x31,
+ 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, 0x74,
+ 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x31,
+ 0x2f, 0x31, 0x34, 0x20, 0x31, 0x32, 0x3a, 0x35, 0x32, 0x3a,
+ 0x32, 0x32, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, 0x3c,
+ 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22,
+ 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x68,
+ 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x6e,
+ 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65,
+ 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e,
+ 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c,
+ 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69,
+ 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x2e,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x5b, 0x4c, 0x69, 0x6e, 0x6b,
+ 0x73, 0x5d, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72,
+ 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x22, 0x3e, 0xa, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, 0x3e, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c,
+ 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+};
+
+static const char data_licence_html[] = {
+ /* /licence.html */
+ 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63,
+ 0x6f, 0x64, 0x65, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x63,
+ 0x65, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c,
+ 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0xa, 0x3c,
+ 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22,
+ 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30,
+ 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22,
+ 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63,
+ 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e,
+ 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22,
+ 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69,
+ 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32,
+ 0x3e, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6c, 0x69,
+ 0x63, 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f, 0x68, 0x32, 0x3e,
+ 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30,
+ 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77,
+ 0x68, 0x69, 0x74, 0x65, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa,
+ 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20,
+ 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x31, 0x2c, 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, 0x2e, 0xa, 0x41,
+ 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20,
+ 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x52,
+ 0x65, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x73,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61,
+ 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2c, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0xa, 0x6d, 0x6f, 0x64,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69,
+ 0x74, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69,
+ 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0xa, 0x61, 0x72, 0x65, 0x20, 0x6d,
+ 0x65, 0x74, 0x3a, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x6f,
+ 0x6c, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x20, 0x52, 0x65,
+ 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x72, 0x65, 0x74, 0x61, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65,
+ 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0xa, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65,
+ 0x72, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0x20, 0xa, 0x3c, 0x62,
+ 0x72, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x20, 0x52, 0x65,
+ 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x62, 0x69, 0x6e,
+ 0x61, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0xa, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65,
+ 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
+ 0x69, 0x6e, 0x67, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x61,
+ 0x69, 0x6d, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0xa, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x2f,
+ 0x6f, 0x72, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d,
+ 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x20, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0xa, 0x64, 0x69, 0x73,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x3c, 0x62, 0x72, 0x3e, 0x20, 0xa, 0x3c, 0x62, 0x72, 0x3e,
+ 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x20, 0x4e, 0x65, 0x69, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20,
+ 0x6e, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73,
+ 0xa, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x6f, 0x72, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65,
+ 0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x20, 0x6f, 0x72, 0x20,
+ 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x70, 0x72,
+ 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x20, 0x64, 0x65, 0x72,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0xa,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77,
+ 0x61, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
+ 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63,
+ 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x77, 0x72, 0x69,
+ 0x74, 0x74, 0x65, 0x6e, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x3c, 0x62, 0x72,
+ 0x3e, 0x20, 0xa, 0x3c, 0x2f, 0x6f, 0x6c, 0x3e, 0xa, 0x3c,
+ 0x62, 0x72, 0x3e, 0xa, 0x54, 0x48, 0x49, 0x53, 0x20, 0x53,
+ 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x49, 0x53,
+ 0x20, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x44, 0x20,
+ 0x42, 0x59, 0x20, 0x54, 0x48, 0x45, 0x20, 0x49, 0x4e, 0x53,
+ 0x54, 0x49, 0x54, 0x55, 0x54, 0x45, 0x20, 0x41, 0x4e, 0x44,
+ 0x20, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54,
+ 0x4f, 0x52, 0x53, 0x20, 0x60, 0x41, 0x53, 0x20, 0x49, 0x53,
+ 0x27, 0x20, 0x41, 0x4e, 0x44, 0x20, 0xa, 0x41, 0x4e, 0x59,
+ 0x20, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x4f,
+ 0x52, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x45, 0x44, 0x20,
+ 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x49, 0x45, 0x53,
+ 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e,
+ 0x47, 0x2c, 0x20, 0x42, 0x55, 0x54, 0x20, 0x4e, 0x4f, 0x54,
+ 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x20, 0x54,
+ 0x4f, 0x2c, 0x20, 0x54, 0x48, 0x45, 0x20, 0xa, 0x49, 0x4d,
+ 0x50, 0x4c, 0x49, 0x45, 0x44, 0x20, 0x57, 0x41, 0x52, 0x52,
+ 0x41, 0x4e, 0x54, 0x49, 0x45, 0x53, 0x20, 0x4f, 0x46, 0x20,
+ 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, 0x4e, 0x54, 0x41, 0x42,
+ 0x49, 0x4c, 0x49, 0x54, 0x59, 0x20, 0x41, 0x4e, 0x44, 0x20,
+ 0x46, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f,
+ 0x52, 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43,
+ 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, 0x52, 0x50, 0x4f,
+ 0x53, 0x45, 0x20, 0xa, 0x41, 0x52, 0x45, 0x20, 0x44, 0x49,
+ 0x53, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x2e, 0x20,
+ 0x20, 0x49, 0x4e, 0x20, 0x4e, 0x4f, 0x20, 0x45, 0x56, 0x45,
+ 0x4e, 0x54, 0x20, 0x53, 0x48, 0x41, 0x4c, 0x4c, 0x20, 0x54,
+ 0x48, 0x45, 0x20, 0x49, 0x4e, 0x53, 0x54, 0x49, 0x54, 0x55,
+ 0x54, 0x45, 0x20, 0x4f, 0x52, 0x20, 0x43, 0x4f, 0x4e, 0x54,
+ 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x53, 0x20, 0x42,
+ 0x45, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x20, 0xa,
+ 0x46, 0x4f, 0x52, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x44, 0x49,
+ 0x52, 0x45, 0x43, 0x54, 0x2c, 0x20, 0x49, 0x4e, 0x44, 0x49,
+ 0x52, 0x45, 0x43, 0x54, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x49,
+ 0x44, 0x45, 0x4e, 0x54, 0x41, 0x4c, 0x2c, 0x20, 0x53, 0x50,
+ 0x45, 0x43, 0x49, 0x41, 0x4c, 0x2c, 0x20, 0x45, 0x58, 0x45,
+ 0x4d, 0x50, 0x4c, 0x41, 0x52, 0x59, 0x2c, 0x20, 0x4f, 0x52,
+ 0x20, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e,
+ 0x54, 0x49, 0x41, 0x4c, 0x20, 0xa, 0x44, 0x41, 0x4d, 0x41,
+ 0x47, 0x45, 0x53, 0x20, 0x28, 0x49, 0x4e, 0x43, 0x4c, 0x55,
+ 0x44, 0x49, 0x4e, 0x47, 0x2c, 0x20, 0x42, 0x55, 0x54, 0x20,
+ 0x4e, 0x4f, 0x54, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45,
+ 0x44, 0x20, 0x54, 0x4f, 0x2c, 0x20, 0x50, 0x52, 0x4f, 0x43,
+ 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x4f, 0x46,
+ 0x20, 0x53, 0x55, 0x42, 0x53, 0x54, 0x49, 0x54, 0x55, 0x54,
+ 0x45, 0x20, 0x47, 0x4f, 0x4f, 0x44, 0x53, 0x20, 0xa, 0x4f,
+ 0x52, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x53,
+ 0x3b, 0x20, 0x4c, 0x4f, 0x53, 0x53, 0x20, 0x4f, 0x46, 0x20,
+ 0x55, 0x53, 0x45, 0x2c, 0x20, 0x44, 0x41, 0x54, 0x41, 0x2c,
+ 0x20, 0x4f, 0x52, 0x20, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x54,
+ 0x53, 0x3b, 0x20, 0x4f, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49,
+ 0x4e, 0x45, 0x53, 0x53, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x52,
+ 0x52, 0x55, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x29, 0x20, 0xa,
+ 0x48, 0x4f, 0x57, 0x45, 0x56, 0x45, 0x52, 0x20, 0x43, 0x41,
+ 0x55, 0x53, 0x45, 0x44, 0x20, 0x41, 0x4e, 0x44, 0x20, 0x4f,
+ 0x4e, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x54, 0x48, 0x45, 0x4f,
+ 0x52, 0x59, 0x20, 0x4f, 0x46, 0x20, 0x4c, 0x49, 0x41, 0x42,
+ 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x20, 0x57, 0x48, 0x45,
+ 0x54, 0x48, 0x45, 0x52, 0x20, 0x49, 0x4e, 0x20, 0x43, 0x4f,
+ 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54, 0x2c, 0x20, 0x53, 0x54,
+ 0x52, 0x49, 0x43, 0x54, 0x20, 0xa, 0x4c, 0x49, 0x41, 0x42,
+ 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x20, 0x4f, 0x52, 0x20,
+ 0x54, 0x4f, 0x52, 0x54, 0x20, 0x28, 0x49, 0x4e, 0x43, 0x4c,
+ 0x55, 0x44, 0x49, 0x4e, 0x47, 0x20, 0x4e, 0x45, 0x47, 0x4c,
+ 0x49, 0x47, 0x45, 0x4e, 0x43, 0x45, 0x20, 0x4f, 0x52, 0x20,
+ 0x4f, 0x54, 0x48, 0x45, 0x52, 0x57, 0x49, 0x53, 0x45, 0x29,
+ 0x20, 0x41, 0x52, 0x49, 0x53, 0x49, 0x4e, 0x47, 0x20, 0x49,
+ 0x4e, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x57, 0x41, 0x59, 0x20,
+ 0xa, 0x4f, 0x55, 0x54, 0x20, 0x4f, 0x46, 0x20, 0x54, 0x48,
+ 0x45, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x46, 0x20, 0x54,
+ 0x48, 0x49, 0x53, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41,
+ 0x52, 0x45, 0x2c, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x20, 0x49,
+ 0x46, 0x20, 0x41, 0x44, 0x56, 0x49, 0x53, 0x45, 0x44, 0x20,
+ 0x4f, 0x46, 0x20, 0x54, 0x48, 0x45, 0x20, 0x50, 0x4f, 0x53,
+ 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x20, 0x4f,
+ 0x46, 0x20, 0xa, 0x53, 0x55, 0x43, 0x48, 0x20, 0x44, 0x41,
+ 0x4d, 0x41, 0x47, 0x45, 0x2e, 0x20, 0x3c, 0x62, 0x72, 0x3e,
+ 0xa, 0xa, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22,
+ 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa,
+ 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65,
+ 0x3d, 0x22, 0x2d, 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa,
+ 0x24, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30,
+ 0x31, 0x2f, 0x31, 0x30, 0x2f, 0x30, 0x38, 0x20, 0x31, 0x33,
+ 0x3a, 0x31, 0x31, 0x3a, 0x34, 0x35, 0x20, 0x24, 0xa, 0x3c,
+ 0x2f, 0x69, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22, 0x3e, 0xa, 0x26,
+ 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c,
+ 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f,
+ 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f,
+ 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d,
+ 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c,
+ 0x6f, 0x67, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
+ 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e,
+ 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22,
+ 0x3e, 0xa, 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,
+ 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, 0x3e, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+
+static const char data_img_sics_gif[] = {
+ /* /img/sics.gif */
+ 0x2f, 0x69, 0x6d, 0x67, 0x2f, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x69, 0x66, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, 0x47,
+ 0x49, 0x46, 0x38, 0x39, 0x61, 0x46, 00, 0x22, 00, 0xa5,
+ 00, 00, 0xd9, 0x2b, 0x39, 0x6a, 0x6a, 0x6a, 0xbf, 0xbf,
+ 0xbf, 0x93, 0x93, 0x93, 0xf, 0xf, 0xf, 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, 00, 00, 00, 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, 00, 00, 00, 00, 0x46,
+ 00, 0x22, 00, 00, 0x6, 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, 0x4, 0xbe, 0x83, 0xe2, 0x60, 0x3c, 0x50, 0x20,
+ 0xd, 0x8e, 0x6f, 00, 0x31, 0x28, 0x1c, 0xd, 0x7, 0xb5,
+ 0xc3, 0x60, 0x75, 0x24, 0x3e, 0xf8, 0xfc, 0x87, 0x11, 0x6,
+ 0xe9, 0x3d, 0x46, 0x7, 0xb, 0x7a, 0x7a, 0x7c, 0x43, 0x6,
+ 0x1e, 0x84, 0x78, 0xb, 0x7, 0x6e, 0x51, 0x1, 0x8a, 0x84,
+ 0x8, 0x7e, 0x79, 0x80, 0x87, 0x89, 0x91, 0x7a, 0x93, 0xa,
+ 0x4, 0x99, 0x78, 0x96, 0x4f, 0x3, 0x9e, 0x79, 0x1, 0x94,
+ 0x9f, 0x43, 0x9c, 0xa3, 0xa4, 0x5, 0x77, 0xa3, 0xa0, 0x4e,
+ 0x98, 0x79, 0xb, 0x1e, 0x83, 0xa4, 0xa6, 0x1f, 0x96, 0x5,
+ 0x9d, 0xaa, 0x78, 0x1, 0x7, 0x84, 0x4, 0x1e, 0x1e, 0xbb,
+ 0xb8, 0x51, 0x84, 0xe, 0x43, 0x5, 0x7, 0x77, 0xa5, 0x7f,
+ 0x42, 0xb1, 0xb2, 0x1, 0x63, 0x8, 0xd, 0xbb, 0x1, 0xc,
+ 0x7a, 0xd, 0x44, 0xe, 0xd8, 0xaf, 0x4c, 0x5, 0x7a, 0x4,
+ 0x47, 0x7, 0x7, 0xb7, 0x80, 0xa2, 0xe1, 0x7d, 0x44, 0x5,
+ 0x1, 0x4, 0x1, 0xd0, 0xea, 0x87, 0x93, 0x4f, 0xe0, 0x9a,
+ 0x49, 0xce, 0xd8, 0x79, 0x4, 0x66, 0x20, 0x15, 0x10, 0x10,
+ 0x11, 0x92, 0x29, 0x80, 0xb6, 0xc0, 0x91, 0x15, 0x45, 0x1e,
+ 0x90, 0x19, 0x71, 0x46, 0xa8, 0x5c, 0x4, 0xe, 00, 0x22,
+ 0x4e, 0xe8, 0x40, 0x24, 0x9f, 0x3e, 0x4, 0x6, 0xa7, 0x58,
+ 0xd4, 0x93, 0xa0, 0x1c, 0x91, 0x3f, 0xe8, 0xf0, 0x88, 0x3,
+ 0xb1, 0x21, 0xa2, 0x49, 00, 0x19, 0x86, 0xfc, 0x52, 0x44,
+ 0xe0, 0x1, 0x9d, 0x29, 0x21, 0x15, 0x25, 0x50, 0xf7, 0x67,
+ 0x25, 0x1e, 0x6, 0xfd, 0x4e, 0x9a, 0xb4, 0x90, 0xac, 0x15,
+ 0xfa, 0xcb, 0x52, 0x53, 0x1e, 0x8c, 0xf2, 0xf8, 0x7, 0x92,
+ 0x2d, 0x8, 0x3a, 0x4d, 0x12, 0x49, 0x95, 0x49, 0xdb, 0x14,
+ 0x4, 0xc4, 0x14, 0x85, 0x29, 0xaa, 0xe7, 0x1, 0x8, 0xa4,
+ 0x49, 0x1, 0x14, 0x51, 0xe0, 0x53, 0x91, 0xd5, 0x29, 0x6,
+ 0x1a, 0x64, 0x2, 0xf4, 0xc7, 0x81, 0x9e, 0x5, 0x20, 0x22,
+ 0x64, 0xa5, 0x30, 0xae, 0xab, 0x9e, 0x97, 0x53, 0xd8, 0xb9,
+ 0xfd, 0x50, 0xef, 0x93, 0x2, 0x42, 0x74, 0x34, 0xe8, 0x9c,
+ 0x20, 0x21, 0xc9, 0x1, 0x68, 0x78, 0xe6, 0x55, 0x29, 0x20,
+ 0x56, 0x4f, 0x4c, 0x40, 0x51, 0x71, 0x82, 0xc0, 0x70, 0x21,
+ 0x22, 0x85, 0xbe, 0x4b, 0x1c, 0x44, 0x5, 0xea, 0xa4, 0x1,
+ 0xbf, 0x22, 0xb5, 0xf0, 0x1c, 0x6, 0x51, 0x38, 0x8f, 0xe0,
+ 0x22, 0xec, 0x18, 0xac, 0x39, 0x22, 0xd4, 0xd6, 0x93, 0x44,
+ 0x1, 0x32, 0x82, 0xc8, 0xfc, 0x61, 0xb3, 0x1, 0x45, 0xc,
+ 0x2e, 0x83, 0x30, 0xd0, 0xe, 0x17, 0x24, 0xf, 0x70, 0x85,
+ 0x94, 0xee, 0x5, 0x5, 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, 0x6,
+ 0xa2, 00, 0x6b, 0x57, 0xca, 0x3d, 0x11, 0x50, 0xbd, 0x4,
+ 0x30, 0x4b, 0x3a, 0xd4, 0xab, 0x5f, 0x1f, 0x9b, 0x3d, 0x13,
+ 0x74, 0x27, 0x88, 0x3c, 0x25, 0xe0, 0x17, 0xbe, 0x7a, 0x79,
+ 0x45, 0xd, 0xc, 0xb0, 0x8b, 0xda, 0x90, 0xca, 0x80, 0x6,
+ 0x5d, 0x17, 0x60, 0x1c, 0x22, 0x4c, 0xd8, 0x57, 0x22, 0x6,
+ 0x20, 00, 0x98, 0x7, 0x8, 0xe4, 0x56, 0x80, 0x80, 0x1c,
+ 0xc5, 0xb7, 0xc5, 0x82, 0xc, 0x36, 0xe8, 0xe0, 0x83, 0x10,
+ 0x46, 0x28, 0xe1, 0x84, 0x14, 0x56, 0x68, 0xa1, 0x10, 0x41,
+ 00, 00, 0x3b, };
+
+static const char data_index_html[] = {
+ /* /index.html */
+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x49, 0x6e, 0x74,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3c,
+ 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68,
+ 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x6d, 0x65, 0x74, 0x61,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x6c,
+ 0x77, 0x49, 0x50, 0x20, 0x2d, 0x20, 0x41, 0x20, 0x46, 0x72,
+ 0x65, 0x65, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x77, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49,
+ 0x50, 0xa, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64,
+ 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3e,
+ 0xa, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x3d, 0x22, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64,
+ 0x73, 0x22, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x2c,
+ 0x20, 0x74, 0x69, 0x6e, 0x79, 0x2c, 0x20, 0x54, 0x43, 0x50,
+ 0x2f, 0x49, 0x50, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b,
+ 0x2c, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0xa, 0x65, 0x6d,
+ 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x2c, 0x20, 0x73, 0x6d,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x72, 0x65, 0x65, 0x2c,
+ 0x20, 0x42, 0x53, 0x44, 0x2d, 0x6c, 0x69, 0x63, 0x65, 0x6e,
+ 0x63, 0x65, 0x2c, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50,
+ 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0xa,
+ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
+ 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa,
+ 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c,
+ 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0x5b, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0xa, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c,
+ 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77,
+ 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32, 0x3e,
+ 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x2f, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c,
+ 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22, 0x3e, 0xa,
+ 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74,
+ 0x65, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22,
+ 0x35, 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73,
+ 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x6c, 0x77, 0x49,
+ 0x50, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61,
+ 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e,
+ 0x64, 0x65, 0x6e, 0x74, 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, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
+ 0x6f, 0x6c, 0xa, 0x73, 0x75, 0x69, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65,
+ 0x65, 0x6e, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x3c, 0x61, 0xa, 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,
+ 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e,
+ 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x61, 0xa, 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, 0x63, 0x6e, 0x61, 0x2f, 0x22, 0x3e,
+ 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x73, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63,
+ 0x74, 0x75, 0x72, 0x65, 0x73, 0xa, 0x6c, 0x61, 0x62, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 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, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x49,
+ 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x6f,
+ 0x66, 0xa, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72,
+ 0x20, 0x53, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x20, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x61,
+ 0xa, 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, 0x63, 0x6e, 0x61, 0x2f,
+ 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2f,
+ 0x22, 0x3e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65,
+ 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x70, 0x72, 0x6f, 0x6a,
+ 0x65, 0x63, 0x74, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa,
+ 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d,
+ 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e,
+ 0xa, 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, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x52, 0x41, 0x4d, 0x20, 0x75, 0x73, 0x61, 0x67,
+ 0x65, 0xa, 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, 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, 0xa, 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,
+ 0x74, 0x68, 0x73, 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, 0xa, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x34,
+ 0x30, 0x20, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20,
+ 0x52, 0x4f, 0x4d, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa,
+ 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d,
+ 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e,
+ 0xa, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x66, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x73, 0x3a, 0xa, 0x3c, 0x75, 0x6c, 0x3e,
+ 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x49, 0x50, 0x20, 0x28, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x29, 0x20, 0x69, 0x6e,
+ 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61,
+ 0x63, 0x6b, 0x65, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x77, 0x61,
+ 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0xa,
+ 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x20, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x49, 0x43, 0x4d, 0x50, 0x20, 0x28,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x43,
+ 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+ 0x63, 0x6f, 0x6c, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e,
+ 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x61, 0x69,
+ 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0xa, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69,
+ 0x6e, 0x67, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x55, 0x44, 0x50,
+ 0x20, 0x28, 0x55, 0x73, 0x65, 0x72, 0x20, 0x44, 0x61, 0x74,
+ 0x61, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0x29, 0x20, 0x69, 0x6e, 0x63, 0x6c,
+ 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78, 0x70, 0x65,
+ 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x55,
+ 0x44, 0x50, 0x2d, 0x6c, 0x69, 0x74, 0x65, 0xa, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0xa,
+ 0x3c, 0x6c, 0x69, 0x3e, 0x54, 0x43, 0x50, 0x20, 0x28, 0x54,
+ 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x29, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x65,
+ 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x72, 0x6f, 0x6c, 0x2c, 0x20, 0x52, 0x54, 0x54, 0xa, 0x65,
+ 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x72,
+ 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x66, 0x61,
+ 0x73, 0x74, 0x20, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x6d, 0x69, 0x74, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x53, 0x70,
+ 0x65, 0x63, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20,
+ 0x6e, 0x6f, 0x2d, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x41, 0x50,
+ 0x49, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x6e, 0x68, 0x61,
+ 0x6e, 0x63, 0x65, 0x64, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20,
+ 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79, 0x20, 0x73,
+ 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x41, 0x50, 0x49, 0xa,
+ 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x2f, 0x70, 0x3e,
+ 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20,
+ 0x66, 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x61, 0x76, 0x61,
+ 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x75, 0x6e,
+ 0x64, 0x65, 0x72, 0x20, 0x61, 0x20, 0x42, 0x53, 0x44, 0x2d,
+ 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x63, 0x65,
+ 0x6e, 0x73, 0x65, 0x29, 0x20, 0x69, 0x6e, 0x20, 0x43, 0x20,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64,
+ 0x65, 0xa, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x70, 0x61, 0x67,
+ 0x65, 0x2e, 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0x3c, 0x68, 0x32, 0x3e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x6e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e,
+ 0xa, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x3c, 0x62, 0x3e, 0x32, 0x30, 0x30, 0x32, 0x2d, 0x30,
+ 0x33, 0x2d, 0x31, 0x39, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x50,
+ 0x61, 0x75, 0x6c, 0x20, 0x53, 0x68, 0x65, 0x65, 0x72, 0x20,
+ 0x68, 0x61, 0x73, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
+ 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72,
+ 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x42, 0x53, 0x44,
+ 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xa, 0x6c, 0x61,
+ 0x79, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x50, 0x61, 0x75, 0x6c, 0x4f, 0x53, 0x20, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x20, 0x48, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x63, 0x6f,
+ 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x64, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x20,
+ 0xa, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x62, 0x3e, 0x32,
+ 0x30, 0x30, 0x32, 0x2d, 0x30, 0x33, 0x2d, 0x31, 0x38, 0x3c,
+ 0x2f, 0x62, 0x3e, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x30, 0x2e, 0x35, 0x2e, 0x33, 0x20, 0x72, 0x65,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x2e, 0x20, 0x43, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x62,
+ 0x75, 0x67, 0x66, 0x69, 0x78, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x61, 0xa, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x71,
+ 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x41, 0x50,
+ 0x49, 0x20, 0x28, 0x61, 0x70, 0x69, 0x5f, 0x6c, 0x69, 0x62,
+ 0x2e, 0x63, 0x29, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62,
+ 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x62,
+ 0x3e, 0x32, 0x30, 0x30, 0x32, 0x2d, 0x30, 0x33, 0x2d, 0x31,
+ 0x38, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x53, 0x74, 0x65, 0x76,
+ 0x65, 0x20, 0x52, 0x65, 0x79, 0x6f, 0x6e, 0x6f, 0x6c, 0x64,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x69, 0x74, 0x65, 0x6c,
+ 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67,
+ 0x69, 0x65, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x68,
+ 0x61, 0x73, 0xa, 0x64, 0x6f, 0x6e, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x49, 0x47, 0x4d, 0x50, 0x76,
+ 0x32, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2e, 0x20,
+ 0x49, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0xa,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x70, 0x61, 0x67,
+ 0x65, 0x2e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62, 0x72, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77,
+ 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x77, 0x73, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa, 0xa, 0x3c, 0x70, 0x20,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73,
+ 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x31, 0x22, 0x3e, 0x3c,
+ 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20,
+ 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x34, 0x2f, 0x30, 0x32,
+ 0x20, 0x30, 0x38, 0x3a, 0x34, 0x31, 0x3a, 0x31, 0x32, 0x20,
+ 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, 0x3c, 0x2f, 0x66, 0x6f,
+ 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22,
+ 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x68,
+ 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x5b, 0x49, 0x6e,
+ 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5d, 0xa, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77,
+ 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44,
+ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73,
+ 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61,
+ 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72,
+ 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x22, 0x3e, 0xa, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, 0x3e, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c,
+ 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+};
+
+static const char data_download_html[] = {
+ /* /download.html */
+ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x44, 0x6f, 0x77,
+ 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x74, 0x69, 0x74,
+ 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
+ 0xa, 0xa, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62,
+ 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68,
+ 0x69, 0x74, 0x65, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c,
+ 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 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, 0x3c,
+ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c,
+ 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0xa,
+ 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x72,
+ 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x6e, 0x74,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x77,
+ 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69,
+ 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4d,
+ 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73,
+ 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x63,
+ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x5b, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x5d, 0xa, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32, 0x3e,
+ 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f,
+ 0x68, 0x32, 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30,
+ 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22,
+ 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63,
+ 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa,
+ 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x35, 0x30, 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73,
+ 0x70, 0x3b, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c,
+ 0x74, 0x64, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x34, 0x30, 0x22,
+ 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66,
+ 0x79, 0x22, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0xa, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20,
+ 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69, 0x63, 0x65,
+ 0x6e, 0x63, 0x65, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x74, 0x68, 0x69, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x42,
+ 0x53, 0x44, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x6c,
+ 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0xa, 0x3c, 0x2f,
+ 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x52, 0x65,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa,
+ 0x54, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69,
+ 0x73, 0x20, 0x30, 0x2e, 0x35, 0x2e, 0x33, 0x2e, 0x20, 0x28,
+ 0x4f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0xa,
+ 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x72, 0x65,
+ 0x61, 0x73, 0x6f, 0x6e, 0x2e, 0x29, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x30,
+ 0x2e, 0x35, 0x2e, 0x33, 0x20, 0x28, 0x6c, 0x61, 0x74, 0x65,
+ 0x73, 0x74, 0x29, 0x3a, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70,
+ 0x2d, 0x30, 0x2e, 0x35, 0x2e, 0x33, 0x2e, 0x74, 0x61, 0x72,
+ 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c, 0x77, 0x69, 0x70, 0x2d,
+ 0x30, 0x2e, 0x35, 0x2e, 0x33, 0x2e, 0x74, 0x61, 0x72, 0x2e,
+ 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0xa, 0x3c, 0x62,
+ 0x72, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x73,
+ 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x32, 0x22, 0x3e, 0xa,
+ 0x4f, 0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x76,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x3c,
+ 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d,
+ 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x35, 0x2e, 0x32,
+ 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c,
+ 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x35, 0x2e, 0x32, 0x2e,
+ 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f,
+ 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x35,
+ 0x2e, 0x31, 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22,
+ 0x3e, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x35, 0x2e,
+ 0x31, 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x2f, 0x3f, 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30,
+ 0x2e, 0x35, 0x2e, 0x30, 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67,
+ 0x7a, 0x22, 0x3e, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e,
+ 0x35, 0x2e, 0x30, 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c, 0x61, 0xa, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70,
+ 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x32, 0x2e, 0x74, 0x61, 0x72,
+ 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c, 0x77, 0x69, 0x70, 0x2d,
+ 0x30, 0x2e, 0x34, 0x2e, 0x32, 0x2e, 0x74, 0x61, 0x72, 0x2e,
+ 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d, 0x6c, 0x77,
+ 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x74,
+ 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c, 0x77, 0x69,
+ 0x70, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x74, 0x61,
+ 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0xa,
+ 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f, 0x66,
+ 0x3d, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x34, 0x2e,
+ 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c, 0x77,
+ 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x74, 0x61, 0x72,
+ 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0xa, 0x3c,
+ 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f,
+ 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d,
+ 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x33, 0x2e, 0x31,
+ 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c,
+ 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x33, 0x2e, 0x31, 0x2e,
+ 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x20, 0xa, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f,
+ 0x3f, 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e,
+ 0x33, 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e,
+ 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x33, 0x2e, 0x74,
+ 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0x20,
+ 0xa, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f,
+ 0x66, 0x3d, 0x6c, 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x32,
+ 0x2e, 0x74, 0x61, 0x72, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x6c,
+ 0x77, 0x69, 0x70, 0x2d, 0x30, 0x2e, 0x32, 0x2e, 0x74, 0x61,
+ 0x72, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x62, 0x72,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0xa, 0x3c,
+ 0x68, 0x33, 0x3e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x3c, 0x70,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75,
+ 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54, 0x68,
+ 0x65, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x20, 0x64,
+ 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x56, 0x53, 0x20, 0x69,
+ 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x76, 0x61,
+ 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3c, 0x61, 0xa,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x3f, 0x66, 0x3d, 0x6c, 0x77,
+ 0x69, 0x70, 0x2d, 0x63, 0x76, 0x73, 0x2e, 0x74, 0x61, 0x72,
+ 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x79, 0xa, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0xa, 0x3c,
+ 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65,
+ 0x20, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x3c, 0x2f, 0x68,
+ 0x33, 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67,
+ 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79,
+ 0x22, 0x3e, 0xa, 0x4a, 0x6f, 0x65, 0x20, 0x4d, 0x61, 0x63,
+ 0x44, 0x6f, 0x6e, 0x61, 0x6c, 0x64, 0x20, 0x68, 0x61, 0x73,
+ 0x20, 0x70, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x48, 0x54,
+ 0x4d, 0x4c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64,
+ 0x65, 0xa, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61,
+ 0x74, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,
+ 0x77, 0x2e, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64,
+ 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x22, 0x3e, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
+ 0x77, 0x77, 0x2e, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x65,
+ 0x64, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6c, 0x77, 0x49, 0x50,
+ 0x2f, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0x20, 0xa, 0x3c, 0x2f,
+ 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x50, 0x6f,
+ 0x72, 0x74, 0x73, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x3c,
+ 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a,
+ 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x46,
+ 0x6c, 0x6f, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x75,
+ 0x6c, 0x7a, 0x65, 0x20, 0x68, 0x61, 0x73, 0x20, 0x70, 0x6f,
+ 0x72, 0x74, 0x65, 0x64, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20,
+ 0x74, 0x6f, 0x20, 0x44, 0x4a, 0x47, 0x50, 0x50, 0x2f, 0x4d,
+ 0x53, 0x2d, 0x44, 0x4f, 0x53, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x20,
+ 0x43, 0x2b, 0x2b, 0xa, 0x36, 0x2e, 0x30, 0x2f, 0x57, 0x69,
+ 0x6e, 0x33, 0x32, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x79, 0x20,
+ 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x64, 0x6f, 0x77,
+ 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, 0x3c, 0x61,
+ 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x70, 0x61,
+ 0x67, 0x65, 0x73, 0x2e, 0x66, 0x68, 0x2d, 0x67, 0x69, 0x65,
+ 0x73, 0x73, 0x65, 0x6e, 0x2e, 0x64, 0x65, 0x2f, 0x7e, 0x68,
+ 0x67, 0x31, 0x30, 0x38, 0x33, 0x36, 0x2f, 0x64, 0x65, 0x76,
+ 0x2f, 0x64, 0x6a, 0x67, 0x70, 0x70, 0x2f, 0x6c, 0x77, 0x69,
+ 0x70, 0x64, 0x6a, 0x67, 0x70, 0x70, 0x74, 0x65, 0x73, 0x74,
+ 0x2d, 0x30, 0x2e, 0x31, 0x2e, 0x7a, 0x69, 0x70, 0x22, 0x3e,
+ 0x68, 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x28,
+ 0x44, 0x4a, 0x47, 0x50, 0x50, 0x2f, 0x4d, 0x53, 0x2d, 0x44,
+ 0x4f, 0x53, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x3c, 0x61,
+ 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x70, 0x61,
+ 0x67, 0x65, 0x73, 0x2e, 0x66, 0x68, 0x2d, 0x67, 0x69, 0x65,
+ 0x73, 0x73, 0x65, 0x6e, 0x2e, 0x64, 0x65, 0x2f, 0x7e, 0x68,
+ 0x67, 0x31, 0x30, 0x38, 0x33, 0x36, 0x2f, 0x63, 0x72, 0x6f,
+ 0x77, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6c, 0x77, 0x69,
+ 0x70, 0x2d, 0x77, 0x69, 0x6e, 0x33, 0x32, 0x2d, 0x6d, 0x73,
+ 0x76, 0x63, 0x2d, 0x30, 0x2e, 0x31, 0x2e, 0x7a, 0x69, 0x70,
+ 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0x28, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x20, 0x43,
+ 0x2b, 0x2b, 0x20, 0x36, 0x2e, 0x30, 0x2f, 0x57, 0x69, 0x6e,
+ 0x33, 0x32, 0x29, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa,
+ 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x41, 0x64, 0x64, 0x2d, 0x6f,
+ 0x6e, 0x73, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73,
+ 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0xa,
+ 0x3c, 0x68, 0x34, 0x3e, 0x44, 0x48, 0x43, 0x50, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x68, 0x34, 0x3e,
+ 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d,
+ 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e,
+ 0xa, 0x4c, 0x65, 0x6f, 0x6e, 0x20, 0x57, 0x6f, 0x65, 0x73,
+ 0x74, 0x65, 0x6e, 0x62, 0x65, 0x72, 0x67, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x41, 0x78, 0x6f, 0x6e, 0x20, 0x44, 0x69,
+ 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x44, 0x65, 0x73, 0x69,
+ 0x67, 0x6e, 0x20, 0x42, 0x2e, 0x56, 0x2e, 0x20, 0x68, 0x61,
+ 0x73, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
+ 0x61, 0x20, 0x43, 0x53, 0x38, 0x39, 0x30, 0x30, 0x61, 0xa,
+ 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x72,
+ 0x69, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x73, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c,
+ 0x79, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x20, 0x44, 0x48, 0x43, 0x50, 0x20,
+ 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0xa, 0x6c, 0x77, 0x49, 0x50, 0x2e, 0x20, 0x54, 0x68, 0x65,
+ 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x6f, 0x74, 0x68,
+ 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x65, 0x73, 0x72, 0x61, 0x63, 0x2e, 0x65, 0x6c, 0x65, 0x2e,
+ 0x74, 0x75, 0x65, 0x2e, 0x6e, 0x6c, 0x2f, 0x7e, 0x6c, 0x65,
+ 0x6f, 0x6e, 0x2f, 0x6c, 0x77, 0x69, 0x70, 0x2f, 0x22, 0x3e,
+ 0x68, 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x69,
+ 0x73, 0xa, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x67, 0x72, 0x61, 0x74, 0x65, 0x20, 0x4c, 0x65, 0x6f, 0x6e,
+ 0x27, 0x73, 0x20, 0x44, 0x48, 0x43, 0x50, 0x20, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x20, 0xa, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62,
+ 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x34, 0x3e, 0x49, 0x47, 0x4d,
+ 0x50, 0x76, 0x32, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f,
+ 0x68, 0x34, 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66,
+ 0x79, 0x22, 0x3e, 0xa, 0x53, 0x74, 0x65, 0x76, 0x65, 0x20,
+ 0x52, 0x65, 0x79, 0x6e, 0x6f, 0x6c, 0x64, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x43, 0x69, 0x74, 0x65, 0x6c, 0x20, 0x54, 0x65,
+ 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73,
+ 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x68, 0x61, 0x73, 0x20,
+ 0x64, 0x6f, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x49, 0x47, 0x4d, 0x50, 0x76, 0x32, 0xa, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x77,
+ 0x49, 0x50, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2e,
+ 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x76, 0x61,
+ 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x69, 0x67,
+ 0x6d, 0x70, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x7a, 0x69,
+ 0x70, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61,
+ 0x3e, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x70,
+ 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x61, 0x6e, 0x64,
+ 0xa, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64,
+ 0x69, 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x73, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x6c, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x2d, 0x20, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x63,
+ 0x65, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x69, 0x67, 0x6d, 0x70, 0x2e, 0x63, 0xa, 0x66,
+ 0x69, 0x6c, 0x65, 0x29, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x65,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x6c, 0x77, 0x49, 0x50, 0xa, 0x64,
+ 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c,
+ 0x68, 0x34, 0x3e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61,
+ 0x74, 0x69, 0x76, 0x65, 0x20, 0x42, 0x53, 0x44, 0x20, 0x73,
+ 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6c, 0x61, 0x79, 0x65,
+ 0x72, 0x3c, 0x2f, 0x68, 0x34, 0x3e, 0xa, 0x3c, 0x70, 0x20,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73,
+ 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x50, 0x61, 0x75,
+ 0x6c, 0x20, 0x53, 0x68, 0x65, 0x65, 0x72, 0x20, 0x68, 0x61,
+ 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x50,
+ 0x61, 0x75, 0x6c, 0x4f, 0x53, 0x20, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73,
+ 0xa, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61,
+ 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74,
+ 0x69, 0x76, 0x65, 0x20, 0x42, 0x53, 0x44, 0x20, 0x73, 0x6f,
+ 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6c, 0x61, 0x79, 0x65, 0x72,
+ 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x76,
+ 0x61, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x62,
+ 0x73, 0x64, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x63,
+ 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f,
+ 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x50, 0x61,
+ 0x75, 0x6c, 0x20, 0x53, 0x68, 0x65, 0x65, 0x72, 0xa, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
+ 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,
+ 0x77, 0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
+ 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x2f, 0x67,
+ 0x70, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x47,
+ 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2e, 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c,
+ 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74,
+ 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d, 0x31, 0x22,
+ 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61, 0x74, 0x65,
+ 0x3a, 0x20, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x33, 0x2f,
+ 0x31, 0x39, 0x20, 0x30, 0x39, 0x3a, 0x30, 0x32, 0x3a, 0x34,
+ 0x32, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e, 0x3c, 0x2f,
+ 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x70, 0x3e,
+ 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35,
+ 0x30, 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e,
+ 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30,
+ 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65,
+ 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d,
+ 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c,
+ 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa,
+ 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20,
+ 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f,
+ 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x5b, 0x44, 0x6f, 0x77,
+ 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5d, 0xa, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e,
+ 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22,
+ 0x3e, 0xa, 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,
+ 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x22, 0x3e, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+
+static const char data_documentation_html[] = {
+ /* /documentation.html */
+ 0x2f, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x44, 0x6f, 0x63,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f,
+ 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x62,
+ 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e,
+ 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30,
+ 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65,
+ 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d,
+ 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c,
+ 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c,
+ 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36,
+ 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22,
+ 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74,
+ 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67,
+ 0x6e, 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22,
+ 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x5b, 0x44, 0x6f, 0x63,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5d, 0xa, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c,
+ 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77,
+ 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32, 0x3e,
+ 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x2f,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65,
+ 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d,
+ 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e,
+ 0x3c, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22, 0x3e,
+ 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69,
+ 0x74, 0x65, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x22, 0x35, 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x75,
+ 0x6c, 0x3e, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6f, 0x73, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x55, 0x73, 0x69, 0x6e, 0x67,
+ 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f,
+ 0x75, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x72,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0xa, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa, 0x3c, 0x62,
+ 0x72, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x6c,
+ 0x69, 0x3e, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x77, 0x49, 0x50,
+ 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x72,
+ 0x63, 0x68, 0x69, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x73, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f,
+ 0x6e, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x6f, 0x72, 0x74, 0x20, 0x6c, 0x77, 0x49, 0x50, 0xa, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x20,
+ 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x75,
+ 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x41, 0x50, 0x49, 0x2e,
+ 0x20, 0x54, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x65, 0xa, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x3a, 0x20,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64,
+ 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x72, 0x63,
+ 0x68, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e, 0x73, 0x79, 0x73,
+ 0x5f, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x74, 0x78, 0x74, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x2f, 0x72, 0x61,
+ 0x77, 0x61, 0x70, 0x69, 0x2e, 0x74, 0x78, 0x74, 0x22, 0x3e,
+ 0x72, 0x61, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x74, 0x78, 0x74,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0x20, 0xa, 0x3c, 0x62, 0x72,
+ 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x3a,
+ 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x6d, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x6d,
+ 0x73, 0x67, 0x30, 0x30, 0x32, 0x33, 0x31, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x6d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66,
+ 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c,
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x2c, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x73,
+ 0x74, 0x2f, 0x6d, 0x73, 0x67, 0x30, 0x30, 0x32, 0x32, 0x37,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x54, 0x68, 0x72,
+ 0x65, 0x61, 0x64, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x6d, 0x61,
+ 0x70, 0x68, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x72, 0x61, 0x77, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x66, 0x61, 0x63, 0x65, 0x20, 0xa, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0x2c, 0x20,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d,
+ 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x6d, 0x73,
+ 0x67, 0x30, 0x30, 0x32, 0x34, 0x32, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73,
+ 0x2c, 0x20, 0x73, 0x65, 0x6d, 0x61, 0x70, 0x68, 0x6f, 0x72,
+ 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0xa, 0x72, 0x61, 0x77,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65,
+ 0x20, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x5b, 0x32, 0x5d, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0x20, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61,
+ 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x6d, 0x73, 0x67,
+ 0x30, 0x30, 0x34, 0x36, 0x30, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x6f, 0x74,
+ 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x76, 0x65,
+ 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e,
+ 0x76, 0x69, 0x72, 0x6f, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x41,
+ 0x44, 0x53, 0xa, 0x31, 0x2e, 0x31, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x41, 0x52, 0x4d, 0x2e, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa,
+ 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x41, 0x20, 0x72, 0x65, 0x70,
+ 0x6f, 0x72, 0x74, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x62, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x65, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e,
+ 0x20, 0x6f, 0x6c, 0x64, 0xa, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x77, 0x49, 0x50,
+ 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x67, 0x6f,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0xa, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
+ 0x6f, 0x6c, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x75, 0x62, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0xa, 0x62, 0x75, 0x66, 0x66, 0x65,
+ 0x72, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x62, 0x65, 0x64, 0x2e, 0x20, 0x41, 0x6c, 0x73, 0x6f,
+ 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x72, 0x65,
+ 0x70, 0x6f, 0x72, 0x74, 0xa, 0x69, 0x73, 0x20, 0x61, 0x20,
+ 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20,
+ 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20,
+ 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+ 0x20, 0x41, 0x50, 0x49, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0xa, 0x65,
+ 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x2e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x2f, 0x6c, 0x77, 0x69, 0x70,
+ 0x2e, 0x70, 0x64, 0x66, 0x22, 0x3e, 0x50, 0x44, 0x46, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x2c, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x2f, 0x6c, 0x77,
+ 0x69, 0x70, 0x2e, 0x70, 0x73, 0x2e, 0x67, 0x7a, 0x22, 0x3e,
+ 0x2e, 0x70, 0x73, 0x2e, 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2e, 0xa, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62, 0x72,
+ 0x3e, 0xa, 0xa, 0x3c, 0x6c, 0x69, 0x3e, 0x53, 0x6c, 0x69,
+ 0x64, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x61, 0x6c, 0x6b, 0x73, 0x20, 0x61, 0x20, 0x62, 0x69, 0x74,
+ 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x3a, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x2f, 0x70, 0x72, 0x65, 0x73,
+ 0x2e, 0x70, 0x64, 0x66, 0x22, 0x3e, 0x50, 0x44, 0x46, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x28, 0x38, 0x36, 0x6b, 0x29, 0x2c,
+ 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x64, 0x6f, 0x63, 0x2f, 0x70, 0x72, 0x65, 0x73, 0x2e, 0x70,
+ 0x73, 0x2e, 0x67, 0x7a, 0x22, 0x3e, 0x2e, 0x70, 0x73, 0x2e,
+ 0x67, 0x7a, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x28, 0x33, 0x36,
+ 0x6b, 0x29, 0x2e, 0x20, 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e,
+ 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x46, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65,
+ 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x67, 0x61, 0x72,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78,
+ 0x79, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0xa, 0x73, 0x75,
+ 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x54, 0x43, 0x50, 0x2f,
+ 0x49, 0x50, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x6c, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x69, 0x6e, 0x20, 0x3c, 0x61, 0xa, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f,
+ 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e, 0x6b, 0x65, 0x6c,
+ 0x73, 0x27, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x73, 0x69, 0x73, 0x3c, 0x2f, 0x61,
+ 0x3e, 0x2e, 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d,
+ 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e,
+ 0xa, 0x54, 0x68, 0x65, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x6d, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0xa, 0x64,
+ 0x69, 0x73, 0x63, 0x75, 0x73, 0x73, 0x20, 0x6c, 0x77, 0x49,
+ 0x50, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c,
+ 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a,
+ 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x46,
+ 0x6f, 0x72, 0x20, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x67, 0x67,
+ 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x70,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x63, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x20, 0x61, 0x74, 0x20, 0x3c, 0x61,
+ 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69,
+ 0x6c, 0x74, 0x6f, 0x3a, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44,
+ 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x20, 0x3c, 0x61, 0x64,
+ 0x61, 0x6d, 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65,
+ 0x3e, 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75,
+ 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0xa, 0x26, 0x6c, 0x74, 0x3b,
+ 0x61, 0x64, 0x61, 0x6d, 0x40, 0x73, 0x69, 0x63, 0x73, 0x2e,
+ 0x73, 0x65, 0x26, 0x67, 0x74, 0x3b, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x2e, 0x20, 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d,
+ 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66, 0x6f,
+ 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x2d,
+ 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44, 0x61,
+ 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30,
+ 0x33, 0x2f, 0x31, 0x38, 0x20, 0x31, 0x33, 0x3a, 0x31, 0x31,
+ 0x3a, 0x35, 0x35, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69, 0x3e,
+ 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x70, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30,
+ 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa,
+ 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22,
+ 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69,
+ 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c,
+ 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74,
+ 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x63,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa, 0x3c,
+ 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x49,
+ 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6e,
+ 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x5b, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0xa, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67,
+ 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x44,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x73,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4c, 0x69, 0x6e,
+ 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0xa, 0xa,
+ 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x72, 0x3e,
+ 0xa, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x22, 0x3e, 0xa, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f,
+ 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75, 0x6e,
+ 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e,
+ 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
+ 0x6c, 0x3e, 0xa, };
+
+static const char data_os_html[] = {
+ /* /os.html */
+ 0x2f, 0x6f, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0xa,
+ 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 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, 0x20, 0x2d, 0x20, 0x4f, 0x53, 0x20,
+ 0x76, 0x73, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x4f, 0x53, 0x3c,
+ 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x2f, 0x68,
+ 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x62, 0x6f,
+ 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e, 0xa,
+ 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22,
+ 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69,
+ 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65, 0x6c,
+ 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d, 0x22,
+ 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74,
+ 0x64, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x3e, 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, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f,
+ 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3e, 0xa, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa,
+ 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e,
+ 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa,
+ 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69,
+ 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c,
+ 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x22, 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69,
+ 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67,
+ 0x20, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c,
+ 0x6f, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43,
+ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c,
+ 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4c,
+ 0x69, 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0xa, 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74,
+ 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x4f,
+ 0x53, 0x20, 0x76, 0x73, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x4f,
+ 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x2f, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22,
+ 0x36, 0x34, 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30,
+ 0x22, 0xa, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0x3c, 0x74,
+ 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x22, 0x3e, 0xa, 0x26,
+ 0x6e, 0x62, 0x73, 0x70, 0x3b, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x20, 0x62, 0x67, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
+ 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35,
+ 0x34, 0x30, 0x22, 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x32, 0x3e,
+ 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x77, 0x49, 0x50,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x20,
+ 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3c, 0x2f, 0x68, 0x32,
+ 0x3e, 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67,
+ 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79,
+ 0x22, 0x3e, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x20,
+ 0x66, 0x65, 0x77, 0x20, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20,
+ 0x68, 0x6f, 0x77, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x63,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x61, 0xa, 0x73, 0x74, 0x61, 0x6e,
+ 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x65, 0x6e, 0x76,
+ 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28,
+ 0x69, 0x2e, 0x65, 0x2e, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x65,
+ 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x74, 0x68, 0x72,
+ 0x65, 0x61, 0x64, 0x65, 0x64, 0xa, 0x6f, 0x70, 0x65, 0x72,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x29, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x6c, 0x79,
+ 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
+ 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x62, 0x65, 0xa, 0x68, 0x6f, 0x77, 0x20,
+ 0x6c, 0x77, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65,
+ 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x2d, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65,
+ 0x64, 0xa, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0xa,
+ 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73,
+ 0x72, 0x63, 0x3d, 0x22, 0x6f, 0x73, 0x2e, 0x70, 0x6e, 0x67,
+ 0x22, 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x3e, 0xa, 0xa, 0x3c, 0x68, 0x33, 0x3e, 0x54, 0x68, 0x65,
+ 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x73, 0x69, 0x6e, 0x67,
+ 0x6c, 0x65, 0x2d, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65,
+ 0x64, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x3c, 0x2f, 0x68, 0x33,
+ 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61,
+ 0x6c, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x50, 0x2c, 0xa, 0x49,
+ 0x43, 0x4d, 0x50, 0x2c, 0x20, 0x55, 0x44, 0x50, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x54, 0x43, 0x50, 0x20, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x2c, 0x20, 0x61,
+ 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
+ 0x74, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0xa,
+ 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x6d, 0x61,
+ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x63,
+ 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e,
+ 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x73, 0xa, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x65, 0x65,
+ 0x64, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6c,
+ 0x77, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20,
+ 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x28, 0x6e,
+ 0x6f, 0x6e, 0x2d, 0x4f, 0x53, 0x29, 0xa, 0x65, 0x6e, 0x76,
+ 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20,
+ 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x3c, 0x70, 0x20, 0x61,
+ 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74,
+ 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x54, 0x68, 0x65, 0x20,
+ 0x63, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+ 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x20, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x20,
+ 0x61, 0x73, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77,
+ 0x61, 0x72, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
+ 0x79, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0xa, 0x66, 0x6f, 0x6c, 0x6c,
+ 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x66, 0x61, 0x63, 0x65, 0x3a, 0xa, 0x3c, 0x2f, 0x70,
+ 0x3e, 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x3c, 0x74, 0x74, 0x3e, 0x69, 0x70, 0x5f, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x28, 0x70, 0x62, 0x75, 0x66, 0x2c, 0x20,
+ 0x6e, 0x65, 0x74, 0x69, 0x66, 0x29, 0x3c, 0x2f, 0x74, 0x74,
+ 0x3e, 0x3a, 0x20, 0x54, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x61,
+ 0x6e, 0x20, 0x49, 0x50, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x6e,
+ 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x61, 0x73, 0x20,
+ 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x61, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0xa, 0x3c, 0x6c, 0x69,
+ 0x3e, 0x3c, 0x74, 0x74, 0x3e, 0x74, 0x63, 0x70, 0x5f, 0x74,
+ 0x6d, 0x72, 0x28, 0x29, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x3a,
+ 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x31, 0x30, 0x30, 0x20, 0x6d, 0x73,
+ 0x2e, 0x20, 0x44, 0x6f, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x54, 0x43, 0x50, 0xa, 0x74, 0x69, 0x6d, 0x65, 0x72,
+ 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20,
+ 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0xa, 0x3c, 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0x3c,
+ 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a,
+ 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x42,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6f, 0x72, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x6e,
+ 0x65, 0x65, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x72,
+ 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61, 0xa, 0x73, 0x69,
+ 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x74, 0x68, 0x72, 0x65, 0x61,
+ 0x64, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f,
+ 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x3c, 0x74, 0x74, 0x3e, 0x73, 0x79, 0x73, 0x5f, 0x61,
+ 0x72, 0x63, 0x68, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x20, 0x28,
+ 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6e, 0x67, 0xa, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x20, 0x61, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x29, 0x20,
+ 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6e,
+ 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6d, 0x70,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x69, 0x6e, 0x67, 0xa, 0x73, 0x65, 0x6d, 0x61, 0x70,
+ 0x68, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x6d,
+ 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x2e, 0x20,
+ 0x49, 0x6e, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x6e,
+ 0x63, 0x79, 0x20, 0x6f, 0x66, 0xa, 0x74, 0x68, 0x65, 0x20,
+ 0x3c, 0x74, 0x74, 0x3e, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x72,
+ 0x63, 0x68, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f,
+ 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x63, 0x61, 0x73,
+ 0x65, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x3c, 0x70,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75,
+ 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x41, 0x20,
+ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x61, 0x69,
+ 0x6e, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d,
+ 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x73,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x6d, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0xa, 0x6c, 0x69, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3a, 0xa, 0x3c, 0x2f,
+ 0x70, 0x3e, 0xa, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x20,
+ 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x31, 0x29, 0x20,
+ 0x7b, 0xa, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x28, 0x70,
+ 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x28, 0x6e, 0x65, 0x74, 0x69, 0x66, 0x29, 0x20, 0x3d, 0x3d,
+ 0x20, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x52, 0x45,
+ 0x41, 0x44, 0x59, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x70, 0x62, 0x75, 0x66, 0x20, 0x3d, 0x20,
+ 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
+ 0x28, 0x6e, 0x65, 0x74, 0x69, 0x66, 0x29, 0x3b, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x70, 0x5f, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x28, 0x70, 0x62, 0x75, 0x66, 0x2c, 0x20,
+ 0x6e, 0x65, 0x74, 0x69, 0x66, 0x29, 0x3b, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0xa, 0xa, 0x20, 0x20, 0x20, 0x20, 0x69,
+ 0x66, 0x28, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x28, 0x29, 0x20,
+ 0x2d, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d,
+ 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x30, 0x30, 0x20, 0x2a,
+ 0x20, 0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, 0x53, 0x29,
+ 0x20, 0x7b, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
+ 0x63, 0x70, 0x5f, 0x74, 0x6d, 0x72, 0x28, 0x29, 0x3b, 0xa,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x61, 0x73, 0x74,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x28, 0x29, 0x3b, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x20, 0x20, 0x20, 0x20, 0xa, 0x20, 0x20, 0x7d,
+ 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65, 0x3e, 0xa, 0xa, 0x3c,
+ 0x68, 0x33, 0x3e, 0x6c, 0x77, 0x49, 0x50, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x73, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa,
+ 0x6c, 0x77, 0x49, 0x50, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65,
+ 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x62, 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x73, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0xa,
+ 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72,
+ 0x72, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61,
+ 0x64, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x64, 0x65, 0x6c, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0xa, 0x63, 0x61, 0x73,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50,
+ 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
+ 0x67, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0xa, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50,
+ 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0xa, 0x73, 0x65,
+ 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x41,
+ 0x50, 0x49, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x69,
+ 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x70, 0x6e, 0x67, 0x22,
+ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+ 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22,
+ 0x3e, 0xa, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x2d, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x70, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0xa, 0x3c, 0x74, 0x74, 0x3e, 0x61,
+ 0x70, 0x69, 0x5f, 0x6c, 0x69, 0x62, 0x2e, 0x63, 0x3c, 0x2f,
+ 0x74, 0x74, 0x3e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x3c, 0x74,
+ 0x74, 0x3e, 0x61, 0x70, 0x69, 0x5f, 0x6d, 0x73, 0x67, 0x2e,
+ 0x63, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x2e, 0x20, 0x54, 0x68,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x72, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67,
+ 0x72, 0x61, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0xa, 0x74, 0x68, 0x65, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49,
+ 0x50, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x41,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2c, 0x20, 0x3c, 0x74, 0x74, 0x3e, 0x74, 0x63, 0x70,
+ 0x69, 0x70, 0x2e, 0x63, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x2c,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0xa, 0x69,
+ 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61,
+ 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x73, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x62, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75,
+ 0x73, 0xa, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x20, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x3c, 0x70,
+ 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6a, 0x75,
+ 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa, 0x57, 0x68,
+ 0x65, 0x6e, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76,
+ 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20,
+ 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x70,
+ 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x64, 0xa, 0x62,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3c, 0x74, 0x74, 0x3e, 0x74,
+ 0x63, 0x70, 0x69, 0x70, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x28, 0x29, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20,
+ 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xa,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x74, 0x74,
+ 0x3e, 0x69, 0x70, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x28,
+ 0x29, 0x3c, 0x2f, 0x74, 0x74, 0x3e, 0x20, 0x66, 0x75, 0x6e,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x77, 0x6f, 0xa, 0x66, 0x75,
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x3c, 0x74, 0x74, 0x3e, 0x74, 0x63, 0x70, 0x69, 0x70, 0x5f,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x28, 0x29, 0x3c, 0x2f, 0x74,
+ 0x74, 0x3e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0xa, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x69,
+ 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79,
+ 0x2e, 0x20, 0x49, 0x74, 0x20, 0x6d, 0x65, 0x72, 0x65, 0x6c,
+ 0x79, 0x20, 0x70, 0x75, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6f, 0x6e,
+ 0x20, 0x61, 0x20, 0x71, 0x75, 0x65, 0x75, 0x65, 0xa, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54,
+ 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0xa,
+ 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x22, 0x3e, 0xa,
+ 0x57, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67,
+ 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x2c, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x63, 0x61, 0x72, 0x65,
+ 0xa, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x3c, 0x74,
+ 0x74, 0x3e, 0x74, 0x63, 0x70, 0x69, 0x70, 0x2e, 0x63, 0x3c,
+ 0x2f, 0x74, 0x74, 0x3e, 0x2e, 0xa, 0x3c, 0x2f, 0x70, 0x3e,
+ 0xa, 0xa, 0x3c, 0x70, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x3c, 0x66,
+ 0x6f, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x22,
+ 0x2d, 0x31, 0x22, 0x3e, 0x3c, 0x69, 0x3e, 0xa, 0x24, 0x44,
+ 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x32, 0x2f,
+ 0x30, 0x32, 0x2f, 0x30, 0x31, 0x20, 0x31, 0x38, 0x3a, 0x32,
+ 0x33, 0x3a, 0x33, 0x35, 0x20, 0x24, 0xa, 0x3c, 0x2f, 0x69,
+ 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c,
+ 0x2f, 0x70, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0xa, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35,
+ 0x30, 0x22, 0x3e, 0xa, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x72, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e,
+ 0xa, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x36, 0x34, 0x30, 0x22,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30,
+ 0x22, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x30, 0x22, 0xa, 0x63, 0x65,
+ 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3d,
+ 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c,
+ 0x74, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0xa, 0xa,
+ 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0xa, 0xa, 0xa, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa,
+ 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
+ 0x6e, 0x65, 0x77, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x4e, 0x65, 0x77, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
+ 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x22, 0x3e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e,
+ 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x61, 0x3e,
+ 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x6d, 0x61, 0x69, 0x6c, 0x69, 0x6e,
+ 0x67, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x22, 0x3e, 0x4d, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20,
+ 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa,
+ 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f,
+ 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x61,
+ 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x22, 0x64, 0x6f, 0x77, 0x6e, 0x6c,
+ 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f,
+ 0x61, 0x3e, 0xa, 0xa, 0x7c, 0xa, 0xa, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x6c, 0x69, 0x6e, 0x6b,
+ 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0xa, 0xa,
+ 0xa, 0x3c, 0x68, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x72,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0xa, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d,
+ 0x2f, 0x22, 0x3e, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x44, 0x75,
+ 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0xa, 0x3c, 0x2f,
+ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3e, 0xa, };
+
+static const char data_threads_png[] = {
+ /* /threads.png */
+ 0x2f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x70, 0x6e, 0x67, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0x89,
+ 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00, 00,
+ 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 0x1, 0x44, 00,
+ 00, 00, 0xf5, 0x8, 0x2, 00, 00, 00, 0xa7, 0x69,
+ 0x1b, 0xf5, 00, 00, 00, 0x9, 0x70, 0x48, 0x59, 0x73,
+ 00, 00, 0xc, 0x4d, 00, 00, 0xc, 0x4d, 0x1, 0xd2,
+ 0xce, 0xad, 0x4e, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58,
+ 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 00,
+ 0x47, 0x4e, 0x55, 0x20, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x36, 0x2e, 0x35, 0x32,
+ 0x19, 0x40, 0x45, 0x56, 00, 00, 0x7, 0x16, 0x49, 0x44,
+ 0x41, 0x54, 0x78, 0x9c, 0xed, 0xdd, 0xdb, 0x76, 0xa3, 0x38,
+ 00, 0x45, 0x41, 0xbb, 0xd7, 0xfc, 0xff, 0x2f, 0x7b, 0x1e,
+ 0xb2, 0x9a, 0x61, 00, 0x13, 0x2e, 0x2, 0xa4, 0xa3, 0xaa,
+ 0xa7, 0xee, 0xc4, 0xc6, 0x8e, 0x9c, 0x8d, 0x84, 0x2f, 0xe4,
+ 0xfd, 0xf9, 0x7c, 0x5e, 0x40, 0xfb, 0xfe, 0xbc, 0x5e, 0xaf,
+ 0xf7, 0xfb, 0xbd, 0x7e, 0xa1, 0xf7, 0x5f, 0x93, 0xff, 0x8e,
+ 0xbf, 0xf8, 0xeb, 0x16, 0x4e, 0xde, 0xd1, 0x52, 0x1b, 0xa9,
+ 0xdf, 0xb1, 0x1f, 0x73, 0xfc, 0xe8, 0xdc, 0x73, 0x8b, 0xc3,
+ 0x75, 0x33, 0x1e, 0x97, 0x86, 0x86, 0xfd, 0x5b, 0x7a, 0x7f,
+ 0xb6, 0x5c, 0xf9, 0x67, 0xf6, 0x1e, 0xcf, 0xe1, 0x9f, 0xcf,
+ 0xe7, 0xd7, 0x29, 0x3d, 0xe3, 0x31, 0xbe, 0xd9, 0xf9, 0x41,
+ 0xdb, 0xbe, 0xd4, 0x1a, 0x6e, 0xeb, 0xcc, 0xea, 0x2c, 0x63,
+ 0x65, 0xd7, 0xd0, 0xb0, 0xff, 0x5c, 0xfd, 0xe7, 0xba, 0x93,
+ 0xbb, 0xbd, 0x29, 0xe6, 0x6f, 0x56, 0xee, 0xcd, 0x96, 0xd9,
+ 0xfe, 0xcc, 0x4d, 0x67, 0x9b, 0xc, 0xce, 0x7c, 0xac, 0xce,
+ 0x8f, 0xde, 0xf6, 0x2d, 0xf4, 0xf3, 0x48, 0x35, 0x31, 0xec,
+ 0xc3, 0x3c, 0x3a, 0xaf, 0xef, 0x9f, 0xc9, 0xf5, 0x87, 0xe2,
+ 0x27, 0xff, 0x38, 0x79, 0xcf, 0x5e, 0x5f, 0x76, 0x48, 0x3f,
+ 0xdb, 0x1f, 0x6f, 0x67, 0xfc, 0xdf, 0xc5, 0xdd, 0x4f, 0xb0,
+ 0xf1, 0xb0, 0xcf, 0xbf, 0xf5, 0xf3, 0x8f, 0x61, 0xf4, 0xbe,
+ 0x8d, 0xe7, 0x6b, 0x69, 0xdc, 0x26, 0x5f, 0xf9, 0x76, 0x95,
+ 0xc5, 0x6b, 0x7d, 0xbb, 0x62, 0x8c, 0x98, 0x61, 0xff, 0xe7,
+ 0xf7, 0x8b, 0x2c, 0x39, 0xd0, 0xdb, 0xe2, 0x25, 0x27, 0x25,
+ 0xcf, 0x2f, 0x39, 0xde, 0x9b, 0xf4, 0x53, 0xf5, 0xdc, 0x30,
+ 0x26, 0xc3, 0x80, 0xcc, 0xbf, 0xf2, 0x1a, 0x8d, 0xe7, 0xe2,
+ 0x5e, 0x78, 0x3c, 0xb0, 0xc3, 0x25, 0xc7, 0xf, 0xc1, 0x64,
+ 0xb4, 0xe7, 0xb7, 0x75, 0xf5, 0x8f, 0x59, 0x9b, 0x9a, 0x87,
+ 0x7d, 0x7e, 0x5b, 0xff, 0x8b, 0x79, 0x72, 0x3, 0xaf, 0xef,
+ 0xbb, 0x84, 0xc9, 0xd7, 0x17, 0x2f, 0xb6, 0xeb, 0xb1, 0x9f,
+ 0x4f, 0xd7, 0xdb, 0xaf, 0x9b, 0x64, 0xf1, 0x1, 0x1e, 0xcc,
+ 0xf7, 0x7d, 0x8b, 0x7b, 0xc3, 0x95, 0x8d, 0x6f, 0x1f, 0xd8,
+ 0x5d, 0x5b, 0x6e, 0x5d, 0x73, 0xc3, 0xbe, 0x78, 0x99, 0xe5,
+ 0x63, 0xe6, 0xa7, 0x5a, 0x5a, 0x7c, 0x8e, 0xae, 0x93, 0x5f,
+ 0xa9, 0x9f, 0x87, 0x7c, 0x50, 0x64, 0x83, 0xe3, 0x7f, 0x6c,
+ 0x1c, 0xc6, 0xc9, 0xb5, 0xe2, 0x35, 0x3a, 0xec, 0x8b, 0xf7,
+ 0x76, 0x21, 0xe6, 0xf1, 0xe2, 0x61, 0x72, 0x7b, 0xe3, 0x9b,
+ 0x3c, 0xbc, 0xff, 0x98, 0x7c, 0x77, 0xb2, 0x6e, 0x59, 0x5c,
+ 0x63, 0xf, 0x37, 0x97, 0xfa, 0x1b, 0x36, 0xf9, 0xe9, 0xe6,
+ 0x3f, 0xec, 0xfb, 0xaf, 0xc9, 0x7a, 0xec, 0xdb, 0x5e, 0x7f,
+ 0x65, 0x7d, 0x38, 0xbf, 0xa1, 0xc5, 0x6b, 0xbd, 0x36, 0xec,
+ 0xd3, 0x5b, 0x7f, 0x5c, 0x9a, 0x1e, 0xf6, 0xc1, 0x7f, 0x5f,
+ 0xef, 0x76, 0x41, 0xdb, 0x90, 0xf9, 0xaf, 0xce, 0xae, 0x95,
+ 0x1b, 0xc7, 0x34, 0x37, 0xec, 0xa7, 0x5e, 0x9a, 0x2, 0xea,
+ 0x21, 0xe6, 0xda, 0x75, 0xfb, 0x24, 0xc2, 0xb3, 0x5a, 0x1c,
+ 0xf6, 0xaa, 0x97, 0xd, 0xc0, 0x76, 0x66, 0x66, 0x8, 0x21,
+ 0x66, 0x8, 0x21, 0x66, 0x8, 0x21, 0x66, 0x8, 0x21, 0x66,
+ 0x8, 0x21, 0x66, 0x8, 0x21, 0xe6, 0x70, 0xf5, 0xbf, 0x3a,
+ 0x1a, 0xe9, 0x91, 0x61, 0x17, 0x33, 0x84, 0x10, 0x33, 0x84,
+ 0x10, 0x33, 0x84, 0x10, 0x33, 0x84, 0x28, 0x19, 0xb3, 0xe7,
+ 0x5a, 0xe0, 0x41, 0x66, 0x66, 0x8, 0x21, 0x66, 0x8, 0x21,
+ 0x66, 0x8, 0x21, 0x66, 0x8, 0x21, 0x66, 0x8, 0x71, 0xf0,
+ 0x24, 0xf8, 0xd4, 0xcc, 0xcb, 0xa, 0x7d, 0x12, 0x73, 0x82,
+ 0xc5, 0x53, 0xb7, 0x2e, 0x7e, 0x8b, 0x60, 0x62, 0x6e, 0xd2,
+ 0x4a, 0xbd, 0x74, 0x4b, 0xcc, 0xd, 0x98, 0xcf, 0xae, 0xea,
+ 0x65, 0x4e, 0xcc, 0x35, 0x32, 0xf1, 0x72, 0x80, 0x98, 0x9f,
+ 0x67, 0xe2, 0xa5, 0x8, 0x31, 0x3f, 0xc0, 0xc4, 0xcb, 0x15,
+ 0xc4, 0x7c, 0x7, 0xf5, 0x72, 0x3, 0x31, 0x97, 0x67, 0xd9,
+ 0xcc, 0x23, 0xc4, 0x5c, 0x80, 0x89, 0x97, 0x1a, 0x88, 0x79,
+ 0x37, 0x13, 0x2f, 0x75, 0x12, 0xf3, 0xef, 0x4c, 0xbc, 0x34,
+ 0x41, 0xcc, 0xb, 0xd4, 0x4b, 0x8b, 0xc4, 0x6c, 0xd9, 0x4c,
+ 0x88, 0x1e, 0x63, 0x36, 0xf1, 0x12, 0x29, 0x3f, 0x66, 0x13,
+ 0x2f, 0x9d, 0x8, 0x8c, 0xd9, 0xc4, 0x4b, 0x9f, 0x12, 0x62,
+ 0x56, 0x2f, 0xbc, 0x9e, 0x8a, 0xf9, 0xfd, 0x7e, 0x1f, 0x4e,
+ 0xce, 0xb2, 0x19, 0x16, 0xdd, 0x1d, 0xf3, 0x90, 0xe2, 0xf6,
+ 0x9e, 0x4d, 0xbc, 0xb0, 0xc5, 0x7d, 0x31, 0x6f, 0x3c, 0x7f,
+ 0x8d, 0x89, 0x17, 0x8e, 0xb9, 0x23, 0xe6, 0xf5, 0x8c, 0x4d,
+ 0xbc, 0x50, 0xc4, 0xb5, 0x31, 0x6f, 0xc9, 0x58, 0xbd, 0x50,
+ 0xc4, 0x55, 0x31, 0x6f, 0x59, 0x54, 0xcb, 0x18, 0xa, 0x2a,
+ 0x1c, 0xf3, 0xae, 0x13, 0xbb, 0x9e, 0x79, 0x4e, 0x1b, 0x98,
+ 0xf0, 0x17, 0x2d, 0x20, 0x44, 0xe1, 0x99, 0xd9, 0x4c, 0xb,
+ 0x4f, 0x31, 0x33, 0x43, 0x8, 0x31, 0x43, 0x88, 0xcb, 0x9f,
+ 00, 0xb3, 0xf0, 0x86, 0x7b, 0x5c, 0x7e, 0xcc, 0xbc, 0xf2,
+ 0xfc, 0xb6, 0xce, 0xa1, 0xa0, 0xcb, 0xdf, 0x1, 0xb6, 0x52,
+ 0xac, 0xce, 0xa1, 0xa0, 0x27, 0x3f, 0x2, 0xa9, 0x73, 0x28,
+ 0xa8, 0xd2, 0xcf, 0x33, 0xeb, 0x1c, 0xf6, 0xaa, 0x34, 0xe6,
+ 0x15, 0x3a, 0x87, 0x45, 0xed, 0xc5, 0xbc, 0x42, 0xe7, 0xf4,
+ 0x2c, 0x2a, 0xe6, 0x15, 0x3a, 0x27, 0x5e, 0x2f, 0x31, 0xaf,
+ 0xd0, 0x39, 0x19, 0xc4, 0xbc, 0xa6, 0xc2, 0xce, 0x7d, 0x8,
+ 0x9c, 0x6f, 0xc4, 0x7c, 0xd0, 0xb3, 0x9d, 0x4b, 0x9a, 0x39,
+ 0x31, 0x97, 0x77, 0x5b, 0xe7, 0xc3, 0xd6, 0x54, 0xcd, 0x4b,
+ 0xcc, 0x37, 0xbb, 0xa8, 0x73, 0x13, 0x35, 0x2f, 0x31, 0xd7,
+ 0xe3, 0x58, 0xe7, 0x8b, 0x17, 0x53, 0x75, 0x9f, 0xc4, 0xdc,
+ 0x80, 0x71, 0x9c, 0x5b, 0xc2, 0x56, 0x75, 0x9f, 0xc4, 0x9c,
+ 0x6c, 0xd7, 0x29, 0xd9, 0xd8, 0xa5, 0xc2, 0xb1, 0x15, 0x73,
+ 0x4b, 0xe, 0x1c, 0x57, 0x57, 0xf8, 0x3b, 0x57, 0xb9, 0x8d,
+ 0x23, 0xb6, 0xbe, 0xea, 0x79, 0x64, 0xd8, 0xc5, 0xdc, 0x18,
+ 0x2b, 0xe7, 0xc3, 0x8a, 0x54, 0x5a, 0x33, 0x31, 0xb7, 0xa4,
+ 0xdd, 0xdf, 0xb3, 0x4b, 0xc5, 0x57, 0xba, 0x91, 0x98, 0xa9,
+ 0x97, 0x4a, 0x77, 0x11, 0x33, 0xf, 0x50, 0xe9, 0x15, 0xc4,
+ 0x4c, 0x49, 0x2a, 0x7d, 0x90, 0x98, 0xd9, 0x44, 0xa5, 0xf5,
+ 0x13, 0x73, 0xef, 0x54, 0x1a, 0x43, 0xcc, 0xb1, 0x86, 0x4a,
+ 0xd7, 0x73, 0x55, 0x69, 0xc, 0x31, 0xb7, 0x67, 0xd7, 0x5c,
+ 0xea, 0x4f, 0x6d, 0xf6, 0x43, 0xcc, 0x15, 0xb1, 0xe2, 0xe5,
+ 0xc, 0x31, 0xdf, 0x41, 0xa5, 0xdc, 0x40, 0xcc, 0xa7, 0xa8,
+ 0x94, 0x7a, 0x88, 0x79, 0x99, 0x4a, 0x69, 0xce, 0x33, 0x31,
+ 0x3f, 0x78, 0x66, 0xc, 0x95, 0x92, 0xea, 0xbe, 0x98, 0xaf,
+ 0xfe, 0x50, 0x98, 0x4a, 0xe9, 0xdc, 0xe5, 0x31, 0x9f, 0x6f,
+ 0x58, 0xa5, 0xb0, 0xc5, 0x85, 0x31, 0xff, 0x1a, 0xa1, 0x4a,
+ 0xa1, 0xa0, 0xf2, 0x31, 0x6f, 0x9f, 0x8a, 0x55, 0xa, 0x5,
+ 0xfd, 0x29, 0xbb, 0x39, 0x27, 0xa9, 0x81, 0xa7, 0x14, 0x9e,
+ 0x99, 0x27, 0x93, 0xad, 0xb6, 0xe1, 0x36, 0xd7, 0x3e, 0x1,
+ 0x36, 0x5f, 0x48, 0xcb, 0x1b, 0x2e, 0x72, 0xf7, 0xeb, 0xcc,
+ 0x8e, 0x93, 0xe1, 0x22, 0x85, 0x8f, 0x99, 0x81, 0xa7, 0x88,
+ 0x19, 0x42, 0x88, 0x19, 0x42, 0x88, 0x19, 0x42, 0x88, 0x19,
+ 0x42, 0x88, 0x19, 0x42, 0x14, 0x7e, 0x69, 0x6a, 0xcb, 0xcb,
+ 0xc8, 0x5e, 0x9d, 0x82, 0x2b, 0x5c, 0xfb, 0xe, 0xb0, 0x45,
+ 0xc7, 0xde, 0x37, 0x62, 0x17, 00, 0xeb, 0x1e, 0x38, 0x39,
+ 0xc1, 0xb1, 0x2c, 0xf, 0xec, 0x2, 0xf4, 0x4f, 0x57, 0x9a,
+ 0x39, 0x6d, 0xd0, 0x81, 0x32, 0xf5, 0x4f, 0x57, 0x9a, 0x89,
+ 0xf9, 0x80, 0x7b, 0xfa, 0x3f, 0x76, 0x43, 0x50, 0x5c, 0x72,
+ 0xcc, 0x7, 0x38, 0x4, 0xa0, 0x5d, 0x62, 0x2e, 0xc0, 0x21,
+ 00, 0x35, 0x10, 0xf3, 0x33, 0x6e, 0x3b, 0x4, 0xa0, 0x1f,
+ 0x62, 0x6e, 0xc6, 0xe1, 0x43, 0x80, 0xbd, 0x7b, 0x1, 0x4b,
+ 0x80, 0x46, 0x89, 0x39, 0xdf, 0xde, 0x38, 0x1d, 0x2, 0x34,
+ 0x4a, 0xcc, 0x4c, 0x79, 0x15, 0x60, 0xee, 0xc1, 0x3f, 0xdb,
+ 0xb0, 0x9d, 0x98, 0x29, 0xa0, 0x93, 0x57, 0x1, 0x86, 0x3b,
+ 0x5c, 0x67, 0xd5, 0x62, 0xe6, 0x31, 0xed, 0xbe, 0xa, 0x50,
+ 0x67, 0xd5, 0x62, 0xa6, 0x25, 0xb5, 0x1d, 0x2, 0x54, 0x55,
+ 0xb5, 0x98, 0x9, 0x77, 0xcf, 0x21, 0xc0, 0xf8, 0xf2, 0x4f,
+ 0x85, 0x2d, 0x66, 0x58, 0x70, 0xe6, 0xc, 0xf0, 0x4f, 0xbd,
+ 0x23, 0x40, 0xcc, 0x70, 0x56, 0x25, 0xe7, 0x87, 0x17, 0x33,
+ 0xec, 0x56, 0xc3, 0x11, 0xf2, 0x9c, 0x98, 0xe1, 0x77, 0x75,
+ 0xd6, 0x3b, 0xe1, 0x1c, 0x60, 0x10, 0x42, 0xcc, 0x10, 0x42,
+ 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc,
+ 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10,
+ 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42,
+ 0xcc, 0xc9, 0x9c, 0x6a, 0xbb, 0x2b, 0x3e, 0x35, 0x15, 0x65,
+ 0x52, 0xef, 0xe7, 0xf3, 0xd1, 0x73, 0x3f, 0xc4, 0xdc, 0xb6,
+ 0x79, 0xbd, 0x4f, 0xdd, 0x13, 0x1e, 0x27, 0xe6, 0x96, 0xcc,
+ 0xa7, 0x59, 0xf5, 0x32, 0x10, 0x73, 0xd5, 0x4c, 0xbc, 0x6c,
+ 0x27, 0xe6, 0x8a, 0x98, 0x78, 0x39, 0x43, 0xcc, 0x4f, 0x32,
+ 0xf1, 0x52, 0x90, 0x98, 0x6f, 0xa5, 0x5e, 0xae, 0x23, 0xe6,
+ 0xb, 0x59, 0x36, 0x73, 0x27, 0x31, 0x97, 0x64, 0xe2, 0xe5,
+ 0x41, 0x62, 0x3e, 0xce, 0xc4, 0x4b, 0x55, 0xc4, 0xbc, 0x83,
+ 0x89, 0x97, 0x9a, 0x89, 0x79, 0x8d, 0x7a, 0x69, 0x88, 0x98,
+ 0xff, 0x63, 0xd9, 0x4c, 0xd3, 0xba, 0x8e, 0xd9, 0xc4, 0x4b,
+ 0x92, 0x8e, 0x62, 0x36, 0xf1, 0x92, 0x2d, 0x39, 0x66, 0x13,
+ 0x2f, 0x5d, 0x89, 0x8a, 0x59, 0xbd, 0xf4, 0xac, 0xe1, 0x98,
+ 0x2d, 0x9b, 0x61, 0xec, 0x81, 0x98, 0x87, 0x8, 0xf7, 0xb6,
+ 0x67, 0xe2, 0x85, 0x15, 0xb7, 0xc6, 0xbc, 0xeb, 0x14, 0x36,
+ 0x26, 0x5e, 0xd8, 0xe5, 0xa6, 0x98, 0xb7, 0x64, 0x6c, 0xe2,
+ 0x85, 0x33, 0x2e, 0x8f, 0x79, 0x25, 0x63, 0xf5, 0x42, 0x41,
+ 0x17, 0xc6, 0xfc, 0xeb, 0x6c, 0xac, 0x5e, 0x28, 0xe8, 0x92,
+ 0xf3, 0x66, 0xbf, 0xdf, 0xef, 0x3, 0xeb, 0x6a, 0xe0, 0x8c,
+ 0xc2, 0x33, 0xb3, 0x3e, 0xe1, 0x29, 0x85, 0x63, 0xfe, 0xb6,
+ 0x72, 0x16, 0x39, 0x5c, 0xed, 0xa6, 0x67, 0xb3, 0x1d, 0x1e,
+ 0xc3, 0xd5, 0xfc, 0xad, 0x29, 0x8, 0x21, 0x66, 0x8, 0x21,
+ 0x66, 0x8, 0x21, 0x66, 0x8, 0x21, 0x66, 0x8, 0x21, 0x66,
+ 0x8, 0x51, 0x38, 0x66, 0xaf, 0x27, 0xc3, 0x53, 0xca, 0xbf,
+ 0x69, 0x64, 0xa5, 0x67, 0xaf, 0x36, 0xc3, 0x75, 0xca, 0xbf,
+ 0x69, 0x64, 0xa5, 0x58, 0x9d, 0xc3, 0x75, 0x6e, 0x3d, 0x39,
+ 0x81, 0xce, 0xe1, 0x3a, 0xb5, 0x9c, 0x3, 0x4c, 0xe7, 0x70,
+ 0x52, 0x2d, 0x31, 0xaf, 0xd0, 0x39, 0x6c, 0xd1, 0x40, 0xcc,
+ 0x2b, 0x74, 0xe, 0x83, 0xb6, 0x63, 0x5e, 0xa1, 0x73, 0x7a,
+ 0x13, 0x1b, 0xf3, 0xa, 0x9d, 0x13, 0xa9, 0xc7, 0x98, 0x57,
+ 0xe8, 0x9c, 0x76, 0x89, 0x79, 0xab, 0x4a, 0x3a, 0x3f, 0xfc,
+ 0x27, 0x4, 0x88, 0x27, 0xe6, 0x2, 0x1e, 0xe9, 0xfc, 0x67,
+ 0xcb, 0x92, 0x66, 0x20, 0xe6, 0x6b, 0x5d, 0xdd, 0xb9, 0x89,
+ 0x9a, 0x81, 0x98, 0x1f, 0x73, 0xac, 0xf3, 0xf5, 0xab, 0x48,
+ 0xba, 0x67, 0x62, 0xae, 0xd1, 0xe1, 0xce, 0x4d, 0xd4, 0x3d,
+ 0x13, 0x73, 0x26, 0x9f, 0x45, 0xed, 0x90, 0x98, 0x5b, 0xb2,
+ 0x31, 0xd1, 0xf1, 0xb4, 0xac, 0xea, 0x7e, 0x88, 0xb9, 0x61,
+ 0xd6, 0xd2, 0x8c, 0x89, 0xb9, 0x25, 0xea, 0x65, 0x85, 0x73,
+ 0x80, 0x41, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31,
+ 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43,
+ 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8,
+ 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31,
+ 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43,
+ 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8,
+ 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31,
+ 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43,
+ 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8,
+ 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31,
+ 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43,
+ 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8,
+ 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31,
+ 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43,
+ 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8, 0x31, 0x43, 0x8,
+ 0x31, 0x43, 0x8, 0x31, 0x43, 0x88, 0x92, 0x31, 0x7f, 0x3e,
+ 0x9f, 0x82, 0x5b, 0xa3, 0x8, 0xf, 0x4a, 0x3f, 0xcc, 0xcc,
+ 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10, 0x42, 0xcc, 0x10,
+ 0xe2, 0x5f, 0x1d, 0x46, 0x9f, 0xd9, 0x7, 0x30, 0xb3, 0xe1,
+ 00, 00, 00, 00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
+ 0x60, 0x82, };
+
+static const char data_os_png[] = {
+ /* /os.png */
+ 0x2f, 0x6f, 0x73, 0x2e, 0x70, 0x6e, 0x67, 0,
+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x6c, 0x77, 0x49, 0x50, 0x2f,
+ 0x70, 0x72, 0x65, 0x2d, 0x30, 0x2e, 0x36, 0x20, 0x28, 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, 0x29,
+ 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
+ 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0x89,
+ 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00, 00,
+ 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 0x2, 0x54, 00,
+ 00, 0x2, 0x13, 0x8, 0x2, 00, 00, 00, 0x4e, 0xa7,
+ 0x15, 0xaa, 00, 00, 00, 0x9, 0x70, 0x48, 0x59, 0x73,
+ 00, 00, 0xc, 0x4d, 00, 00, 0xc, 0x4d, 0x1, 0xd2,
+ 0xce, 0xad, 0x4e, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58,
+ 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 00,
+ 0x47, 0x4e, 0x55, 0x20, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x36, 0x2e, 0x35, 0x32,
+ 0x19, 0x40, 0x45, 0x56, 00, 00, 0x20, 00, 0x49, 0x44,
+ 0x41, 0x54, 0x78, 0x9c, 0xed, 0xdd, 0xdb, 0x9a, 0xa3, 0xaa,
+ 0x16, 0x6, 0x50, 0x6b, 0x7f, 0xeb, 0xfd, 0x5f, 0xb9, 0xf6,
+ 0x45, 0x7a, 0xb9, 0x6c, 0x41, 0x82, 0x67, 0x60, 0x8e, 0x71,
+ 0xd5, 0x9d, 0x32, 0xc6, 0x78, 0xe0, 0x77, 0xa2, 0x91, 0x9f,
+ 0xdf, 0xdf, 0xdf, 0x89, 0x7e, 0xfc, 0xfc, 0xfc, 0xac, 0x5e,
+ 0xb1, 0x5, 0x1, 0xf6, 0xfa, 0xe7, 0xed, 0x5, 0x18, 0x4a,
+ 0x9a, 0x4c, 0x97, 0x4b, 0xa3, 0xee, 0x95, 0xf, 0x5, 0xe8,
+ 0xda, 0x8f, 0x76, 0xed, 0xab, 0xfa, 0x74, 0x19, 0x75, 0x65,
+ 0x5a, 0x3, 0xc0, 0x60, 0x84, 0xdf, 0x1f, 0x85, 0xf6, 0xdd,
+ 0x2a, 0xaa, 0xf7, 0x35, 0x26, 0xad, 0x4c, 0xa0, 0x5, 0x11,
+ 0xc3, 0x2f, 0xdb, 0x40, 0x7, 0x5c, 0xf, 0xaf, 0x70, 0x92,
+ 0x1, 0xb4, 0x60, 0xfc, 0xf0, 0x73, 0x87, 0x48, 0x17, 0xb6,
+ 0x42, 0xd1, 0xc6, 0x2, 0xee, 0x30, 0x66, 0xf8, 0xad, 0x5a,
+ 0xd2, 0x21, 0xbf, 0x63, 0x10, 0xce, 0x5d, 0x80, 0x3b, 0x8c,
+ 0x13, 0x7e, 0xcb, 0x56, 0x72, 0x98, 0x2f, 0x45, 0xca, 0x99,
+ 0xd, 0x70, 0x5e, 0xdf, 0xe1, 0x27, 0xf0, 0x90, 0x85, 0xc0,
+ 0x1, 0x5d, 0x86, 0xdf, 0xdc, 0xde, 0xf5, 0xb8, 0xf0, 0xdc,
+ 0xca, 0xf9, 0x10, 0x50, 0xa3, 0xa7, 0xf0, 0xeb, 0x34, 0xf3,
+ 0x1e, 0xf8, 0x11, 0x7a, 0x83, 0x5a, 0xd8, 0x46, 0x82, 0x10,
+ 0xd8, 0xd2, 0x41, 0xf8, 0xb5, 0xd9, 0x84, 0xf9, 0xdd, 0x77,
+ 0xd9, 0x25, 0x91, 0x7f, 0xe1, 0xaa, 0x6b, 0x73, 0x2f, 0x2,
+ 0xde, 0xd2, 0x74, 0xf8, 0x7d, 0x1a, 0xac, 0xb7, 0x96, 0xb0,
+ 0xdc, 0x7c, 0xb7, 0xbc, 0xde, 0x86, 0x71, 0x20, 0x41, 0x6b,
+ 0xb6, 0x4b, 0xa7, 0x5d, 0x8, 0xc0, 0x85, 0x1a, 0xd, 0xbf,
+ 0x27, 0x63, 0xcf, 0x2f, 0xcc, 0x46, 0xb2, 0xab, 0x22, 0x97,
+ 0x82, 0x8f, 0xf9, 0xf9, 0x69, 0xb4, 0xa9, 0xa1, 0x60, 0xec,
+ 0xad, 0xd6, 0xdc, 0x77, 0xbb, 0x3b, 0xf6, 0xfc, 0x6e, 0x8c,
+ 0xa9, 0x2e, 0x23, 0xed, 0x18, 0x27, 0x6d, 0x1d, 0x6b, 0xc7,
+ 0x8e, 0xf1, 0xc3, 0x2d, 0xc3, 0xb2, 0x5, 0xbf, 0xb5, 0x79,
+ 0xa9, 0x9f, 0xf9, 0xbb, 0x7d, 0x5a, 0xcb, 0x65, 0x98, 0xad,
+ 0x56, 0x51, 0xf6, 0x4f, 0xab, 0xf7, 0x56, 0x2e, 0xff, 0x6a,
+ 0xe2, 0x76, 0x6e, 0xcf, 0x6e, 0x68, 0x54, 0x87, 0x3b, 0x76,
+ 0x8, 0x51, 0x47, 0x56, 0x76, 0x37, 0x58, 0x15, 0x82, 0x9e,
+ 0x53, 0x7a, 0x46, 0x7a, 0x38, 0xc7, 0xbc, 0xf3, 0xab, 0x4d,
+ 0x69, 0x20, 0x7d, 0x4e, 0x11, 0x1e, 0xdb, 0x6a, 0xf3, 0x21,
+ 0xf6, 0x62, 0x71, 0xd9, 0x44, 0xf8, 0x5d, 0x18, 0x7b, 0xed,
+ 0x9c, 0x56, 0xd0, 0x9d, 0xbd, 0xf5, 0x81, 0xe7, 0x94, 0x7e,
+ 0xb5, 0x6c, 0xda, 0xd2, 0x7f, 0x3c, 0xb3, 00, 0x8f, 0x7d,
+ 0x56, 0x2f, 0xb6, 0x76, 0xef, 0x79, 0x5d, 0x65, 0xb7, 0xda,
+ 0x78, 0x5e, 0xe, 0xbf, 0x4b, 0x62, 0xcf, 0x8d, 0x7c, 0x5c,
+ 0xab, 0xb2, 0x77, 0xae, 0xf0, 0x27, 0xb9, 0x38, 0xdb, 0x2a,
+ 0x26, 0x96, 0xd7, 0x5c, 0x67, 0x5b, 0x35, 0xf7, 0x6a, 0xa5,
+ 0x55, 0x1e, 0xf2, 0xd9, 0xd6, 0x3c, 0xfb, 0xf6, 0xf4, 0xa4,
+ 0xb9, 0x66, 0x9a, 0xec, 0xa2, 0x56, 0x7e, 0x44, 0x59, 0xe5,
+ 0x9a, 0xa9, 0x5c, 0x5d, 0x5f, 0xa5, 0xdb, 0xe2, 0x58, 0x17,
+ 0xee, 0x72, 0xcb, 0xb6, 0xbf, 0x9f, 0xbf, 0x16, 0x7e, 0x27,
+ 0x63, 0x4f, 0xe0, 0x71, 0xb7, 0x33, 0x17, 0xa8, 0xf6, 0xe6,
+ 0xe2, 0x78, 0xfb, 0xf0, 0xaa, 0x5d, 0x2e, 0xb4, 0x86, 0xe9,
+ 0x94, 0x53, 0xdd, 0xca, 0xff, 0x34, 0xb2, 0xe5, 0x39, 0x67,
+ 0xe7, 0x50, 0xce, 0x8c, 0x55, 0xdb, 0xb2, 0xfa, 0x88, 0x65,
+ 0x4e, 0x94, 0xaf, 0x66, 0x2d, 0xdf, 0xbe, 0x9c, 0x7f, 0x76,
+ 0xca, 0xad, 0xe5, 0x9f, 0x8a, 0x6b, 0x26, 0x2d, 0xd1, 0x4e,
+ 0x56, 0xba, 0xf5, 0x5b, 0xed, 0xa4, 0x16, 0xee, 0x35, 0x7b,
+ 0x27, 0xfc, 0xe, 0xaf, 0xd3, 0x16, 0x56, 0x19, 0xa1, 0xcc,
+ 0xcd, 0xc1, 0x55, 0xbb, 0x5c, 0xf9, 0x72, 0xe3, 0xd7, 0x29,
+ 0xfb, 0xb2, 0xd5, 0x52, 0x9f, 0xb1, 0xa, 0x83, 0x69, 0xbb,
+ 0xc5, 0x3f, 0xf6, 0x71, 0x69, 0xbc, 0x2d, 0x5f, 0xaf, 0x49,
+ 0x97, 0xaf, 0xb, 0x76, 0x5e, 0xb6, 0x6e, 0xce, 0x2e, 0x43,
+ 0xfa, 0xc6, 0x9a, 0x99, 0x4f, 0xd5, 0x5b, 0x2d, 0x5d, 0x2d,
+ 0xbd, 0xdc, 0x4d, 0xf6, 0x42, 0xf8, 0x1d, 0x38, 0x6, 0x64,
+ 0x1e, 0xef, 0xda, 0xaa, 0x21, 0x2e, 0x9c, 0x7f, 0xfa, 0x62,
+ 0xd7, 0xb7, 0x6b, 0x6d, 0x55, 0x4b, 0x5f, 0xad, 0x8a, 0x8f,
+ 0x63, 0xdd, 0xce, 0x57, 0xa9, 0xec, 0xad, 0xfd, 0xfa, 0xf6,
+ 0xe7, 0x2f, 0x3d, 0x1e, 0xae, 0x2e, 0x8e, 0x6d, 0xb5, 0xd5,
+ 0x5b, 0xba, 0xd8, 0x51, 0x1f, 0xd, 0xbf, 0xbd, 0xeb, 0x45,
+ 0xe6, 0xd1, 0x8e, 0x33, 0xbd, 0xa0, 0x67, 0x3e, 0x71, 0xa9,
+ 0xaf, 0x38, 0x3c, 0xd9, 0xc1, 0xf3, 0xb5, 0x33, 0xf3, 0xe4,
+ 0xa7, 0x14, 0xa4, 0x1f, 0x31, 0xbf, 0x9e, 0x4e, 0x9c, 0x2e,
+ 0xc0, 0xd6, 0xdb, 0xb3, 0x8b, 0x7a, 0xa0, 0x55, 0x3c, 0xf9,
+ 0x7d, 0xd3, 0xbe, 0xdc, 0x65, 0xae, 0x1f, 0x9e, 0x7f, 0xcb,
+ 0xbb, 0x62, 0xd6, 0x73, 0xe1, 0xb7, 0x6b, 0x9d, 0x76, 0x74,
+ 0xfa, 0x40, 0x28, 0x97, 0xf7, 0x82, 0x1e, 0xf8, 0xf4, 0xa5,
+ 0xc6, 0xe3, 0xf0, 0xc0, 0xb5, 0xf9, 0xb4, 0xcf, 0x70, 0x55,
+ 0x7e, 0xa5, 0x4d, 0x76, 0xcd, 0x3c, 0x8f, 0x4d, 0xb6, 0xaa,
+ 0xf6, 0xb6, 0xee, 0x8b, 0x29, 0xdf, 0xf6, 0xb2, 0xea, 0x45,
+ 0x4c, 0x27, 0xa8, 0xb4, 0xfa, 0xb8, 0x33, 0x1b, 0x3a, 0xed,
+ 0xab, 0x2c, 0xdf, 0x10, 0x94, 0x35, 0xaf, 0xae, 0xec, 0xfd,
+ 0x41, 0xab, 0x59, 0xfd, 0x2c, 0x7e, 0x4a, 0x31, 0xbd, 0x77,
+ 0x4, 0x2d, 0x3d, 0xb4, 0x4, 0xf5, 0x5f, 0x55, 0xec, 0xd1,
+ 0x85, 0x16, 0x8e, 0xde, 0xac, 0xb4, 0x81, 0x7e, 0x6b, 0x49,
+ 0xe, 0x6b, 0x3c, 0xd1, 0x2f, 0xd7, 0xec, 0xbe, 0x34, 0xb6,
+ 0x27, 0x2a, 0xbf, 0xfa, 0xd3, 0xae, 0x69, 0xf4, 0xbd, 0x9c,
+ 0x61, 0x34, 0x7b, 0x79, 0x23, 0x5b, 0xbb, 0x64, 0xff, 0xd4,
+ 0xb2, 0xad, 0x42, 0x64, 0x3c, 0x92, 0xef, 0x2d, 0xb7, 0xaf,
+ 0xf7, 0x9a, 0x4d, 0xdb, 0x66, 0x23, 0x2, 0x35, 0x3a, 0x6a,
+ 0xbc, 0x7a, 0x29, 0xa, 0x7b, 0x59, 0x4e, 0xba, 0x76, 0xef,
+ 0x71, 0xfb, 0xb5, 0x5d, 0x10, 0x7b, 0xc, 0xa0, 0xa3, 0xfc,
+ 0x5b, 0xea, 0xb4, 0x28, 0x84, 0x4b, 0xdc, 0xf8, 0x1b, 0xc6,
+ 0x33, 0xb1, 0x37, 0x76, 0x47, 0x7, 0x11, 0xf4, 0x15, 0x27,
+ 0x82, 0x90, 0x68, 0x6e, 0xb9, 0xe6, 0x57, 0x93, 0x7c, 0x5f,
+ 0xf, 0x30, 0x47, 0x20, 0x7d, 0x49, 0x6f, 0x44, 0xec, 0xc8,
+ 0x81, 0x9b, 0xfd, 0xa0, 0x6b, 0x4f, 0xff, 0xc8, 0x5d, 0x3f,
+ 0x27, 0xa3, 0xfa, 0xed, 0xe4, 0x91, 0x86, 0x5f, 0x65, 0x83,
+ 0x70, 0x80, 0xef, 0x5, 0x4b, 0xd7, 0x87, 0x5f, 0xe1, 0xf8,
+ 0x1f, 0xa3, 0x69, 0x80, 0x2d, 0xc3, 0xe4, 0xdf, 0x2c, 0x5b,
+ 0xcb, 0x8e, 0xf4, 0x5, 0x9, 0xeb, 0xe2, 0xf0, 0x93, 0x7c,
+ 0x4, 0x77, 0xe0, 0xa1, 0x50, 0x5d, 0x50, 0xe, 0x32, 0x98,
+ 0x2b, 0xc3, 0x4f, 0xf2, 0x41, 0x4, 0x69, 0x39, 0xe8, 0xe8,
+ 0xa6, 0x3b, 0x97, 0x85, 0x9f, 0xe4, 0x83, 0x8f, 0x51, 0x8b,
+ 0xbf, 0x94, 0x14, 0xa4, 0x5f, 0xb7, 0xdf, 0xf0, 0x22, 0xf9,
+ 0x88, 0x29, 0xd4, 0x9e, 0x2f, 0x5, 0xe9, 0xce, 0x35, 0xe1,
+ 0xb7, 0x75, 0x9c, 0x87, 0x3a, 0xfe, 0x61, 0x69, 0xbc, 0x9b,
+ 0x5f, 0x6a, 0x1c, 0x78, 0xea, 0x34, 0xbc, 0xe2, 0x82, 0xf0,
+ 0x93, 0x7c, 0xc0, 0xca, 0x72, 0x28, 0x83, 0x49, 0xa, 0xd2,
+ 0x9e, 0xbb, 0xba, 0x3d, 0x25, 0x1f, 0xc4, 0x2c, 0xfe, 0x96,
+ 0x14, 0x82, 0x34, 0xeb, 0x6c, 0xf8, 0x6d, 0xd, 0xcf, 0x68,
+ 0x2f, 0x87, 0x49, 0xfe, 0xfd, 0x4b, 0x21, 0x48, 0x6b, 0x4e,
+ 0x85, 0xdf, 00, 0xc9, 0xd7, 0xd7, 0xd2, 0x42, 0xd7, 0x14,
+ 0x82, 0xb4, 0xe3, 0x7f, 0xd7, 0xce, 0xae, 0xaf, 0x2c, 0x9,
+ 0x72, 0x3f, 0x3a, 0xef, 0x8a, 0xf3, 0xcb, 0x87, 0x7a, 0xbf,
+ 0xbf, 0xbf, 0xe9, 0x60, 0xe2, 0xf0, 0xa4, 0xe3, 0x95, 0x5f,
+ 0x5f, 0x39, 0xb7, 0x65, 0x80, 0xaf, 0x40, 0xfb, 0x74, 0x7e,
+ 0x66, 0xe9, 0xb, 0xe5, 0x45, 0xf, 0x3d, 0xe1, 0xe5, 0xc2,
+ 0x8f, 0x98, 0xff, 0xbd, 0x3a, 0x72, 0xa6, 0xbf, 0x3b, 0x55,
+ 0x56, 0x3, 0x6d, 0xa7, 0x7, 0x98, 0xc6, 0x8, 0x5a, 0xa0,
+ 0x2f, 0x94, 0x57, 0x1c, 0xc, 0xbf, 0x34, 0x39, 0x1e, 0xcb,
+ 0x92, 0x65, 0x98, 0x65, 0xe3, 0x2d, 0x5d, 0x9e, 0xf9, 0xdf,
+ 0xfa, 0x58, 0x78, 0x8b, 0xe2, 0xef, 0xab, 0xe5, 0x41, 0x6a,
+ 0x45, 0x71, 0xb7, 0xa7, 0x87, 0x34, 0x3a, 0x63, 0xd9, 0x76,
+ 0xac, 0xa, 0xbb, 0xd5, 0x64, 0x53, 0x72, 0x3a, 0x99, 0xbe,
+ 0xe8, 0xe8, 0x82, 0x6, 0xcd, 0x11, 0xe8, 0x8, 0xe5, 0x56,
+ 0x47, 0xc2, 0xef, 0xc5, 0xb2, 0x6f, 0xa5, 0xf2, 0x43, 0xd3,
+ 0xa5, 0xbd, 0x67, 0x71, 0xa0, 0x44, 0xf1, 0x57, 0xaf, 0x70,
+ 0x76, 0xb, 0x97, 0xb8, 0xf1, 0x9, 0x2f, 0x4f, 0x5a, 0xe5,
+ 0x99, 0x61, 0xe2, 0xa1, 0x77, 0x7a, 0x41, 0xb9, 0xd5, 0xee,
+ 0xf0, 0x7b, 0x37, 0xea, 0x96, 0x47, 0xc2, 0xea, 0xe, 0xf2,
+ 0xc2, 0x52, 0x15, 0x2e, 0xd, 0xc2, 0x93, 0x14, 0x7f, 0x7b,
+ 0x89, 0x40, 0x6e, 0x72, 0xcb, 0x13, 0x5e, 0x6e, 0x92, 0x7e,
+ 0x50, 0xf6, 0xa3, 0x57, 0x2f, 0x96, 0xff, 0xb, 0xb4, 0xcf,
+ 0x85, 0x40, 0x2e, 0xb7, 0xef, 0x47, 0xee, 0x76, 0x3e, 0xe0,
+ 0x2d, 0x7e, 0x17, 0xcf, 0x85, 0x4e, 0x3d, 0xe1, 0x45, 0x16,
+ 0xc2, 0x5e, 0x1e, 0xf8, 0x72, 0xc6, 0xfc, 0x68, 0x98, 0xb7,
+ 0x17, 0x84, 0xee, 0x5d, 0xfc, 0x78, 0x33, 0x80, 0xbb, 0x29,
+ 0x1, 0x39, 0x6f, 0x47, 0xf8, 0xad, 0xea, 0x3c, 0x65, 0x1f,
+ 0x1c, 0xa3, 0x76, 0x39, 0x4f, 0x9, 0xc8, 0x49, 0x2a, 0x3f,
+ 0xa0, 0x57, 0xf2, 0x8f, 0xc3, 0x6a, 0xc3, 0x2f, 0x2d, 0xfb,
+ 0xee, 0x59, 0x1e, 0x80, 0x1d, 0x74, 0x81, 0x72, 0xcc, 0xf1,
+ 0xca, 0x4f, 0x9f, 0x27, 0x1c, 0xa6, 0x64, 0xb9, 0x90, 0x2e,
+ 0x50, 0xe, 0xd0, 0xed, 0x9, 0x8c, 0x40, 0xfe, 0xb1, 0x4b,
+ 0x55, 0xf8, 0xb9, 0xb7, 0x5, 0x68, 0x9f, 0xfc, 0xa3, 0xde,
+ 0x91, 0xca, 0x4f, 0x16, 0xc2, 0x79, 0x5a, 0xea, 0x3b, 0x58,
+ 0xab, 0x54, 0xd2, 0xed, 0x9, 0xc, 0x45, 0xfe, 0x51, 0x23,
+ 0x4a, 0xf8, 0x39, 0x18, 0xe, 0x3b, 0xb0, 0xea, 0xd2, 0x81,
+ 0x85, 0x8f, 0xcd, 0x7, 0x8e, 0x91, 0x7f, 0x7c, 0xf5, 0x3d,
+ 0xfc, 0xc6, 0xf8, 0x6d, 0x7b, 0xfd, 0x32, 0x3b, 0x66, 0x56,
+ 0xae, 0xda, 0xdc, 0x3d, 0xee, 0x36, 0xf, 0xb0, 0xbf, 0xdd,
+ 0x44, 0xfe, 0x51, 0x16, 0xa5, 0xf2, 0x9b, 0x95, 0x8f, 0x7,
+ 0x47, 0x4b, 0xc1, 0x85, 0x2b, 0xc7, 0x7a, 0xfe, 0x70, 0x42,
+ 00, 0x6f, 0xb9, 0x60, 0x30, 0xdb, 0xf6, 0xad, 0x6, 0x3,
+ 0x9b, 0x5b, 0xde, 0xfa, 0x11, 0xfe, 0x2a, 0x7, 0xe, 0x1c,
+ 0x4f, 0x61, 0xd5, 0xad, 0x46, 0x49, 0xdc, 0x5a, 0x2d, 0x9f,
+ 0x3f, 0xa5, 0xe3, 0xb1, 0xad, 0xb6, 0x42, 0xfa, 0x7a, 0xfa,
+ 0x27, 0xd8, 0xc5, 0xe8, 0x89, 0x14, 0x7c, 0xa9, 0xfc, 0xc6,
+ 0xd8, 0x75, 0xd2, 0x21, 0xfd, 0xd2, 0xd6, 0x3c, 0x3b, 0xe5,
+ 0x3c, 0xcd, 0xef, 0xc2, 0x7d, 0xcb, 0xd9, 0xa0, 0xad, 0x55,
+ 0x37, 0xef, 0x18, 0x95, 0x35, 0x5c, 0x76, 0x2c, 0xc6, 0x74,
+ 0xe, 0x91, 0x57, 0x35, 0x77, 0xd0, 0xf9, 0xc9, 0x16, 0xe3,
+ 0xf9, 0x4d, 0xd3, 0xbf, 0xd, 0xf1, 0x90, 0x5f, 0xed, 0xe,
+ 0xf3, 0x8a, 0x4a, 0x83, 0x70, 0x7e, 0xd0, 0x54, 0xe5, 0x13,
+ 0xa7, 0xac, 0x73, 0xee, 0x26, 0xff, 0xc8, 0xa, 0x77, 0xcd,
+ 0xaf, 0xa0, 0x70, 0x84, 0xcc, 0x7f, 0x72, 0x14, 0x15, 0x2c,
+ 0xcf, 0x21, 0xe6, 0x27, 0x4e, 0xed, 0x8d, 0xb7, 0x68, 0xab,
+ 0x5a, 0xd3, 0xfc, 00, 0x2b, 0x99, 0x54, 0x29, 0xfc, 0x22,
+ 0xec, 0x2e, 0xcb, 0x92, 0x25, 0xed, 0xb, 0x5d, 0x5d, 0xd6,
+ 0x1a, 0xb5, 0xf0, 0xad, 0x37, 0xd7, 0x76, 0xab, 0xe2, 0xef,
+ 0xfc, 0xac, 0xac, 0x6a, 0xe0, 0x49, 0xa5, 0x26, 0x26, 0x6d,
+ 0x80, 0x1e, 0x6b, 0x92, 0xb4, 0x7d, 0xd, 0xba, 0x70, 0xa3,
+ 0xc, 0xbf, 0x7d, 0x77, 0x7d, 0xc1, 0xe1, 0xd7, 0x46, 0x23,
+ 0xac, 0x67, 0x96, 0x74, 0x7b, 0x2, 0x10, 0xce, 0xbe, 0x91,
+ 0xdc, 0xef, 0x5b, 0xe, 0x1a, 0xe7, 0x47, 0x7e, 0xb7, 0xb2,
+ 0x4e, 0x1e, 0xe0, 0xca, 0x1f, 0x4b, 0xfb, 0x2a, 0x3f, 0x9d,
+ 0x6, 0x61, 0x5d, 0x78, 0x37, 0xac, 0x1b, 0x6b, 0x57, 0xac,
+ 0x8d, 0xc7, 0xc8, 0x3f, 0x66, 0x9b, 0xe1, 0xa7, 0x7f, 0x1c,
+ 0x80, 0x51, 0xb9, 0xe6, 0x7, 0x4, 0xa2, 0xf8, 0xe3, 0x43,
+ 0xf8, 0x1, 0x10, 0x8e, 0xf0, 0xe3, 0xb, 0x43, 0x1a, 0x1,
+ 0xe3, 0xc9, 0x87, 0x9f, 0xb, 0x7e, 0xcc, 0xc, 0x69, 0xf4,
+ 00, 0x7d, 0x71, 0x4f, 0xb2, 0xb6, 0x99, 0x54, 0x7e, 0xd4,
+ 0x7b, 0xa5, 0xbd, 0xd0, 0x48, 0x1, 0x77, 0x8, 0x31, 0xa4,
+ 0xd1, 0xf4, 0xf7, 0xc0, 0x3a, 0x4b, 0xab, 0x17, 0xe7, 0xc7,
+ 0x51, 0x66, 0xa7, 0x5c, 0xcd, 0x70, 0xeb, 0x4f, 0x23, 0xb9,
+ 0x69, 0x48, 0xa3, 0x5d, 0xeb, 0xdc, 0xe0, 0x47, 0xc0, 0xe5,
+ 0xa2, 0x84, 0xdf, 0xc7, 0xea, 0x51, 0xcb, 0x85, 0x91, 0x7,
+ 0xd2, 0x29, 0x97, 0x7f, 0x8d, 0xd3, 0x2d, 0x9c, 0x9e, 0x1c,
+ 0x4c, 0x8b, 0x67, 0x6f, 0xd6, 0x3f, 0x84, 0x73, 0x39, 0x9f,
+ 0xad, 0xb7, 0x6c, 0xad, 0xf3, 0xad, 0xe7, 0xaf, 0x6, 0xd9,
+ 0x4, 0xdc, 0xe1, 0xd8, 0x53, 0xd7, 0x19, 0x49, 0xac, 0xf0,
+ 0xdb, 0xe2, 0x18, 0xd8, 0x65, 0x59, 0xc9, 0xa5, 0xf, 0xa7,
+ 0xfe, 0x58, 0x95, 0x7a, 0x17, 0x7e, 0x28, 0xc0, 0x79, 0x99,
+ 0x6b, 0x7e, 0x61, 0x4f, 0x88, 0x76, 0xb5, 0xad, 0xd1, 0x46,
+ 0xde, 0xa9, 0x51, 0x3f, 0xa4, 0xd1, 0x25, 0x6b, 0xcf, 0x26,
+ 00, 0xe, 0xab, 0xbd, 0xe1, 0xa5, 0xeb, 0x44, 0x5c, 0xdd,
+ 0x6a, 0xbf, 0xec, 0xed, 0x4c, 0xfb, 0xf1, 0xb6, 0xa6, 0x5c,
+ 0xce, 0x2a, 0xec, 0xc8, 0x3b, 0x97, 0xc, 0x69, 0x74, 0x60,
+ 0x9d, 0xa7, 0xf5, 0xe5, 0x90, 0x9b, 0x40, 0x8a, 0xc3, 0x63,
+ 0x32, 0xd, 0x47, 0xb6, 0x35, 0x79, 0xb8, 0x89, 0x19, 0xa9,
+ 0x45, 0x1b, 0xc6, 0x2b, 0x1b, 0xa5, 0xd3, 0x3d, 0xe1, 0xd8,
+ 0x62, 0x77, 0xfa, 0x65, 0xfb, 0x65, 0x85, 0x47, 0xe6, 0xa7,
+ 0xe, 00, 0x84, 0x23, 0xfc, 0xa8, 0xe2, 0x47, 0x7e, 0xcd,
+ 0x9a, 0xbb, 0x85, 0xb3, 0xaf, 0x4f, 0xdf, 0x56, 0xe3, 0xb1,
+ 0x95, 0xfc, 0xee, 0xa6, 0xb1, 0x63, 0x70, 0x9e, 0xbb, 0x3d,
+ 0xa9, 0xf2, 0x4a, 0xef, 0x90, 0x2e, 0xa9, 0x1a, 0xd9, 0xfb,
+ 0x60, 0x97, 0x57, 0x46, 0xcb, 0xab, 0xd1, 0x4a, 0x26, 0xa6,
+ 0x75, 0xe5, 0xa7, 0x13, 0x1c, 0x3a, 0x55, 0x53, 0xf, 0x75,
+ 0x54, 0x33, 0x75, 0xb4, 0xa8, 0xf4, 0x48, 0xe5, 0x7, 0x23,
+ 0x48, 0x1f, 0x23, 0xb0, 0xec, 0xf3, 0x5c, 0x9e, 0xd1, 0x2e,
+ 0x6f, 0x75, 0x5e, 0xdd, 0x3a, 0xfb, 0xf5, 0x29, 0x48, 0x85,
+ 0xe7, 0xf8, 0x2c, 0xa7, 0x5f, 0x7e, 0x6e, 0x3a, 0xdb, 0xf2,
+ 0xaf, 0x5f, 0xd2, 0xe7, 0xf8, 0x6c, 0x3d, 0x69, 0x61, 0x6b,
+ 0xfa, 0xf2, 0x7, 0xc1, 0x87, 0xf0, 0x83, 0x71, 0xa4, 0x3d,
+ 0x37, 0x69, 0x9e, 0xa5, 0xe1, 0x94, 0x4e, 0xbf, 0x7a, 0xce,
+ 0x4e, 0xfa, 0x10, 0x83, 0xac, 0xaf, 0x61, 0x53, 0x98, 0x60,
+ 0xeb, 0x23, 0xb6, 0x7e, 0x2d, 0x9a, 0x9d, 0x5e, 0xc7, 0x15,
+ 0xf5, 0xdc, 0xf0, 0xc2, 0x17, 0x7, 0x7a, 0x9f, 0xb2, 0x3f,
+ 0x8e, 0xbc, 0xaa, 0x17, 0x6b, 0xeb, 0xfa, 0x16, 0x5f, 0x9f,
+ 0xb3, 0x7a, 0x58, 0x65, 0xec, 0xa5, 0xbf, 0xa0, 0x2d, 0x4c,
+ 0xb0, 0xf7, 0x23, 0xe0, 0x5a, 0xc2, 0x8f, 0x2f, 0xc, 0x69,
+ 0xf4, 0x98, 0x36, 0x1f, 0xe1, 0x56, 0x79, 0x29, 0x71, 0x7e,
+ 0xb8, 0x4f, 0xfa, 0x7a, 0x61, 0x82, 0xca, 0x8f, 0x58, 0xf6,
+ 0xe8, 0x5e, 0x35, 0x25, 0xc1, 0xed, 0x8, 0x3f, 0x3b, 0xd3,
+ 0x14, 0x7b, 0x25, 0x5c, 0xf8, 0xdd, 0x6f, 0x5a, 0x8d, 0xb6,
+ 0xce, 0xb4, 0x71, 0x79, 0xaf, 0xf2, 0xed, 0xd9, 0xe7, 0xec,
+ 0x2c, 0x3b, 0x18, 0xb, 0x33, 0x4c, 0xab, 0xba, 0xf4, 0x6a,
+ 0xdc, 0xd6, 0xdb, 0xb7, 0x3e, 0xa2, 0xfe, 0x69, 0x3e, 0x3,
+ 0x3f, 0xf7, 0x87, 0x9b, 0xac, 0x77, 0x91, 0xf2, 0xee, 0xf5,
+ 0xd8, 0xfe, 0x74, 0xf9, 0x67, 0xd5, 0x5c, 0xcc, 0x9f, 0x36,
+ 0xae, 0xcf, 0xcf, 0x7f, 0x9a, 0x8a, 0x97, 0xd3, 0x87, 0xbc,
+ 0xd2, 0xbe, 0x75, 0xc9, 0x27, 0x7b, 0xaf, 0xc4, 0xf2, 0x5d,
+ 0xab, 0xe1, 0x17, 0x56, 0xb7, 0x5d, 0xd4, 0xac, 0xab, 0x6c,
+ 0xe3, 0xfb, 0xf5, 0x95, 0xf4, 0x12, 0xd1, 0x2b, 0xdb, 0xe5,
+ 0xf0, 0xe, 0x3c, 0x52, 0xab, 0xdd, 0xfe, 0x77, 0x69, 0x7f,
+ 0x9, 0xb9, 0xcf, 0x5f, 0x37, 0xbc, 0xc, 0xbf, 0x2b, 0xa4,
+ 0x17, 0xf3, 0xb, 0xa7, 0xa2, 0xe9, 0x65, 0xff, 0xf9, 0x4f,
+ 0x53, 0x72, 0x76, 0x39, 0xea, 0xaa, 0xdb, 0xba, 0xd1, 0x6e,
+ 0x8e, 0x99, 0xca, 0x2f, 0x5e, 0xb8, 0xed, 0x62, 0x6b, 0xe,
+ 0xab, 0x6a, 0x60, 0xb5, 0x2d, 0xb6, 0xb6, 0xce, 0x94, 0x94,
+ 0x3e, 0x43, 0x6e, 0x97, 0xc6, 0x95, 0x57, 0xfb, 0xd6, 0x99,
+ 0x25, 0x3c, 0xc9, 0xdd, 0x9e, 0xd3, 0x74, 0xf4, 0xe9, 0xcc,
+ 0x61, 0x3b, 0xd9, 0x96, 0x95, 0xdc, 0x32, 0xbd, 0xb6, 0x3a,
+ 0xac, 0x6a, 0x66, 0x95, 0x92, 0x5b, 0x5d, 0x2b, 0x6c, 0x3e,
+ 0x9b, 0x95, 0x16, 0xb8, 0xe1, 0xe5, 0x3f, 0x27, 0xc3, 0xcc,
+ 0x95, 0xf6, 0xdf, 0x7f, 0xcd, 0xff, 0x3e, 0xd3, 0xfb, 0x77,
+ 0xe0, 0x95, 0xf2, 0xac, 0xc2, 0x6e, 0x97, 0xe7, 0x15, 0xee,
+ 0x6d, 0x81, 0x46, 0x84, 0x8, 0xbf, 0x9a, 0x8b, 0xf9, 0xcb,
+ 0x4b, 0x53, 0xd9, 0x29, 0x97, 0x73, 0x4b, 0xcb, 0x9d, 0x20,
+ 0x57, 0xda, 0x57, 0xdf, 0x7d, 0x3a, 0x71, 0x16, 0x9f, 0xce,
+ 0x6a, 0x29, 0xdb, 0xe7, 0x39, 0x6f, 0x8e, 0xec, 0x2b, 0xf3,
+ 0x6c, 0x97, 0xff, 0x8, 0xb2, 0x5d, 0x80, 0xbd, 0x36, 0xef,
+ 0x53, 0xc8, 0x4c, 0xda, 0xf3, 0xd, 0x2f, 0x57, 0x69, 0x76,
+ 0xc1, 0x1e, 0x70, 0xe1, 0x77, 0x1f, 0x7e, 0x35, 0xba, 0xe1,
+ 0xa5, 0xb, 0xd6, 0x76, 0x64, 0xae, 0xf9, 0xf1, 0x3e, 0x77,
+ 0x40, 0xf0, 0x3c, 0xc9, 0x17, 0x9c, 0xf0, 0xdb, 0x21, 0xf2,
+ 0x45, 0xa3, 0xb, 0xbf, 0xbb, 0xa8, 0x3, 0x5e, 0xf7, 0x5f,
+ 0xf8, 0x39, 0xf, 0xfa, 0x2a, 0xf2, 0xfa, 0xb9, 0xf0, 0xbb,
+ 0x47, 0x5e, 0x8d, 0x40, 0x23, 0x42, 0xdc, 0xf0, 0x2, 0xbd,
+ 0x88, 0xfc, 0x13, 0x1a, 0x78, 0x92, 0xf0, 0x3, 0xc2, 0xd1,
+ 0xd1, 0x85, 0xf0, 0xfb, 0x22, 0xfb, 0x6b, 0x7, 00, 0xba,
+ 0xb6, 0x23, 0xfc, 0x82, 0x74, 0xc8, 0xa4, 0x8f, 0x29, 0x99,
+ 0x62, 0xdf, 0xea, 0x52, 0x60, 0xb5, 0xd0, 0x23, 0x65, 0x1f,
+ 0x93, 0xbb, 0x3d, 0x67, 0xf3, 0xf1, 0xb0, 0x3a, 0x2a, 0x1c,
+ 0x24, 00, 0xe3, 0x89, 0xd2, 0xed, 0x59, 0xae, 0x51, 0x54,
+ 0x30, 0x27, 0x59, 0x81, 0xf4, 0xc2, 0xbe, 0xca, 0x47, 0xa0,
+ 0xca, 0x2f, 0x7d, 0xa4, 0xd9, 0xd6, 0x34, 0xe9, 0xe8, 0x62,
+ 0xaf, 0xf, 0x91, 0xf3, 0xa2, 0xe5, 0x83, 0xdf, 0xbe, 0xae,
+ 0xba, 0x29, 0x59, 0x27, 0xd1, 0x56, 0x17, 0xed, 0xb3, 0x1f,
+ 0x32, 0x85, 0xa, 0xbf, 0xad, 0x1, 0x33, 0xa7, 0x64, 0x98,
+ 0x82, 0xe5, 0x8b, 0xf5, 0xe3, 0x1d, 0x8e, 0x6d, 0xf9, 0xe0,
+ 0x53, 0x23, 0x3d, 0xd1, 0x29, 0x3b, 0x24, 0xb3, 0x3f, 0xe1,
+ 0x17, 0x73, 0x9f, 0x8, 0xf8, 0x95, 0xef, 0x16, 0xe4, 0xae,
+ 0x28, 0xa0, 0x77, 0x51, 0xae, 0xf9, 0x15, 0xec, 0x6d, 0xac,
+ 0xdd, 0x2, 0xba, 0xeb, 0x8b, 0x5b, 0x5d, 0x34, 0x22, 0xe6,
+ 0x29, 0x3e, 0x5b, 0xf6, 0x85, 0xdf, 0x30, 0xe7, 0xf5, 0x5b,
+ 0x7d, 0x74, 0xe9, 0x94, 0x86, 0xc8, 0x99, 0xb6, 0x7, 0x81,
+ 0x9a, 0x92, 0xe1, 0x9f, 0x7e, 0x42, 0x8e, 0xf4, 0x44, 0xfb,
+ 0xec, 0x81, 0xac, 0x44, 0xb9, 0xe6, 0x97, 0x8e, 0x3f, 0xb7,
+ 0xf5, 0x93, 0x86, 0xe5, 0xeb, 0xd9, 0x7f, 0x47, 0x3b, 0x84,
+ 0xd2, 0xef, 0x5b, 0x18, 0x81, 0x2f, 0xfd, 0x6f, 0xb4, 0xd5,
+ 0x5, 0x74, 0x41, 0xb7, 0x27, 0x30, 0x38, 0x65, 0x1f, 0x29,
+ 0xe1, 0xc7, 0x59, 0x63, 0xf4, 0x84, 0x33, 0x2a, 0xc9, 0x47,
+ 0x96, 0xf0, 0xe3, 0xac, 0xdf, 0xdf, 0x5f, 0x8d, 0xcb, 0x85,
+ 0x86, 0xb9, 0xb2, 0xde, 0x2, 0xc9, 0xc7, 0x16, 0xe1, 0x7,
+ 0x8c, 0x49, 0xf2, 0x51, 0xb0, 0x3b, 0xfc, 0x9c, 0x96, 0x2,
+ 0xed, 0x93, 0x7c, 0x94, 0xa9, 0xfc, 0xbe, 0x30, 0xa4, 0x11,
+ 0x74, 0x47, 0xf2, 0xf1, 0x55, 0xdc, 0xf0, 0xab, 0x89, 0x34,
+ 0x3f, 0xd0, 0x86, 0xee, 0x48, 0x3e, 0x6a, 0x44, 0xf9, 0x9d,
+ 0xdf, 0x61, 0x8e, 0x22, 0x4d, 0x9, 0x1d, 0xb1, 0xbb, 0x52,
+ 0x29, 0x4a, 0xe5, 0xa7, 0x74, 0x3b, 0xa6, 0xb0, 0xde, 0xac,
+ 0x52, 0x5a, 0x23, 0xf9, 0xa8, 0xf7, 0xcf, 0xb4, 0x7f, 0x8f,
+ 0xc9, 0xe, 0x77, 0xd0, 0xbe, 0x74, 0xcc, 0x9d, 0xf4, 0x91,
+ 0x5d, 0xe9, 0xf0, 0xe, 0x86, 0x34, 0x9a, 0x65, 0xc7, 0x70,
+ 0x58, 0xfe, 0xb7, 0x30, 0x25, 0xdc, 0xad, 0xc7, 0x46, 0x89,
+ 0x17, 0x5, 0xea, 0xf6, 0x4c, 0x9f, 0x33, 0x99, 0x7d, 0xf2,
+ 0xe4, 0x2a, 0xff, 0x82, 0xf, 0x69, 0x94, 0x1d, 0xc9, 0x68,
+ 0xf9, 0xd7, 0xc9, 0x30, 0x46, 0xbc, 0x2d, 0x3d, 0x43, 0x85,
+ 0xaf, 0xa2, 0x74, 0x7b, 0xce, 0x2a, 0x9f, 0x54, 0x49, 0x3d,
+ 0x2b, 0x90, 0x17, 0x7d, 0x4e, 0xb6, 0xec, 0x84, 0xec, 0x15,
+ 0x2e, 0xfc, 0x52, 0x86, 0x34, 0xaa, 0x54, 0xff, 0xc5, 0xc3,
+ 0xae, 0x22, 0x9e, 0x64, 0xb4, 0x10, 0xce, 0x38, 0xd8, 0xed,
+ 0xd9, 0xe3, 0x65, 0xbf, 0xaf, 0xd7, 0xfc, 0xa6, 0x5c, 0x63,
+ 0xbd, 0x1c, 0xa3, 0xe7, 0x73, 0x82, 0x39, 0xff, 0xf2, 0xaf,
+ 0xaf, 0xaf, 0x7f, 0xc6, 0x7c, 0x35, 0x74, 0xf5, 0xc5, 0xb3,
+ 0x17, 0x4d, 0x63, 0xae, 0x22, 0x1e, 0xd6, 0x5d, 0xfb, 0x43,
+ 0x6b, 0xc2, 0x5d, 0xf3, 0xdb, 0xfa, 0xef, 0xd7, 0x57, 0xc2,
+ 0x8e, 0xd1, 0x53, 0xf8, 0xe2, 0x86, 0x31, 0xe2, 0x15, 0x92,
+ 0x8f, 0xf3, 0x2, 0x85, 0x1f, 0xd0, 0x3b, 0x3d, 0xa, 0x5c,
+ 0x25, 0x44, 0xf8, 0xb9, 0xf2, 0x74, 0x39, 0xab, 0x94, 0x87,
+ 0x89, 0x3d, 0xae, 0x75, 0x3c, 0xfc, 0x3a, 0xba, 0xec, 0xd7,
+ 0xc5, 0x42, 0xf6, 0xc5, 0x2a, 0xbd, 0x55, 0x47, 0x7, 0xd7,
+ 0x33, 0xac, 0xd, 0x2e, 0x17, 0xa2, 0xf2, 0x3, 0x3a, 0xa5,
+ 0xe0, 0xe3, 0x26, 0xc2, 0xf, 0x68, 0x91, 0xd8, 0xe3, 0x56,
+ 0xa7, 0x7e, 0xe7, 0x67, 0x6c, 0x3f, 0xe0, 0xe, 0x7e, 0xba,
+ 0xce, 0xdd, 0xfc, 0xc8, 0x9d, 0x1b, 0x39, 0x37, 0x62, 0x2f,
+ 0x3f, 0x5d, 0xe7, 0x19, 0x11, 0xc3, 0xcf, 0x48, 0x5, 0xbb,
+ 0x9c, 0x59, 0x27, 0xe7, 0x9b, 0x30, 0x5b, 0x24, 0x8e, 0x39,
+ 0xf6, 0x24, 0x1f, 0xf, 0x8, 0x17, 0x7e, 0x92, 0x6f, 0x97,
+ 0xb, 0x57, 0x57, 0xf6, 0xe9, 0x39, 0x87, 0x3f, 0x9d, 0x91,
+ 0x88, 0x3d, 0x9e, 0x77, 0xf6, 0x86, 0x97, 0x2e, 0xee, 0xc9,
+ 0xae, 0x69, 0xc1, 0x2b, 0x7, 0x2d, 0x8a, 0x3c, 0x58, 0x4f,
+ 0xfd, 0x90, 0x46, 0xcb, 0xe9, 0xb3, 0x2b, 0xb6, 0x72, 0x54,
+ 0xa9, 0xca, 0xc5, 0xa0, 0x5f, 0xee, 0x6a, 0xe1, 0x2d, 0x81,
+ 0xee, 0xf6, 0xcc, 0x3e, 0xc0, 0x73, 0xd9, 0x88, 0xaf, 0xee,
+ 0xdf, 0x49, 0xf, 0xc8, 0xf6, 0x63, 0xfe, 0x72, 0x7, 0x86,
+ 0x34, 0x4a, 0xdf, 0x9b, 0x4e, 0x5f, 0x9e, 0x43, 0x3a, 0xaa,
+ 0xe2, 0x2c, 0xe0, 0x26, 0x18, 0x95, 0xd8, 0xe3, 0x5d, 0x21,
+ 0xba, 0x3d, 0x97, 0x2d, 0xec, 0xea, 0x4f, 0xd9, 0xa2, 0xb0,
+ 0x30, 0x3d, 0xa9, 0xf3, 0xed, 0x97, 0x16, 0x30, 0x14, 0x9d,
+ 0x9c, 0xb4, 0xe0, 0x82, 0xf0, 0x6b, 0xff, 0x7, 0xf, 0x5b,
+ 0x47, 0xda, 0xd6, 0x62, 0x17, 0x8e, 0xcc, 0xc8, 0x83, 0xf5,
+ 0x34, 0xf2, 0xdd, 0x1b, 0x59, 0xc, 0xe, 0x10, 0x7b, 0xb4,
+ 0x23, 0x4a, 0xb7, 0x67, 0xb6, 0xf7, 0x6c, 0x39, 0xf8, 0xce,
+ 0x72, 0xe8, 0xa2, 0x9a, 0xe9, 0x43, 0x1d, 0xbd, 0x95, 0x43,
+ 0x1a, 0x1d, 0x9b, 0xf3, 0x6a, 0xe, 0xd9, 0xea, 0x7c, 0xbe,
+ 0xb4, 0x1c, 0x76, 0x13, 0xf4, 0xce, 0x26, 0xa3, 0x35, 0xff,
+ 0x35, 0x2b, 0x67, 0x67, 0x74, 0xe9, 0xc5, 0x18, 0x97, 0x76,
+ 0xda, 0x77, 0x7e, 0x1b, 0xd, 0xbc, 0x95, 0xad, 0x9c, 0x99,
+ 0xd8, 0xa3, 0x4d, 0x51, 0x2a, 0x3f, 0xee, 0x96, 0x56, 0x6c,
+ 0xda, 0xbb, 0xe0, 0xc4, 0x1e, 0x2d, 0xfb, 0x67, 0x98, 0x13,
+ 0x4c, 0x9e, 0x74, 0x3e, 0xea, 0x5c, 0xb1, 0x1b, 0x98, 0xd8,
+ 0xa3, 0x7d, 0x97, 0x55, 0x7e, 0x5d, 0xfc, 0xe0, 0x8f, 0xab,
+ 0xb8, 0xc3, 0x93, 0x2c, 0xb1, 0x47, 0x2f, 0x74, 0x7b, 0x42,
+ 0x8b, 0xba, 0x3b, 0x9b, 0x14, 0x7b, 0xf4, 0x45, 0xf8, 0x1,
+ 0xc7, 0x9d, 0xbf, 0xe3, 0x17, 0x5e, 0x71, 0x65, 0xf8, 0x75,
+ 0x77, 0xae, 0xa, 0x1c, 0xa6, 0xd4, 0xa3, 0x6b, 0x2a, 0x3f,
+ 0x60, 0x1f, 0xb1, 0xc7, 00, 0x2e, 0x7e, 0xbc, 0x59, 0xfb,
+ 0x4f, 0x7b, 0x61, 0xaf, 0xbb, 0x37, 0xe8, 0xf9, 0xd1, 0x21,
+ 0x78, 0x8c, 0x47, 0xb4, 0x30, 0xc, 0x95, 0x1f, 0x25, 0xe5,
+ 0x1, 0x31, 0x2e, 0x1f, 0xae, 0xef, 0xeb, 0x3c, 0x25, 0xdf,
+ 0x2b, 0x5c, 0xd8, 0x63, 0x3c, 0xd7, 0x87, 0x5f, 0x83, 0x57,
+ 0xfe, 0x56, 0xc3, 0x8, 0x2c, 0x47, 0xc, 0x28, 0x8f, 0xe4,
+ 0x60, 0xf4, 0x9c, 0xa5, 0xbd, 0x43, 0x1a, 0x6d, 0xbd, 0xa5,
+ 0x3c, 0x68, 0x91, 0x41, 0x8e, 0x9a, 0xa2, 0x87, 0x93, 0x51,
+ 0x5, 0xaa, 0xfc, 0xca, 0x7, 0xb0, 0x1, 0x8c, 0xb2, 0xce,
+ 0xc, 0x69, 0xb4, 0x7c, 0xb1, 0x7e, 0xd0, 0x22, 0x83, 0x1c,
+ 0x35, 0x42, 0xec, 0x31, 0xb6, 0x88, 0x43, 0x1a, 0xad, 0x8e,
+ 0x67, 0x3, 0x18, 0x9d, 0x54, 0xd3, 0x3e, 0xee, 0x6d, 0x43,
+ 0xb5, 0xb9, 0x6f, 0xf9, 0xf9, 0x97, 0xb, 0x7b, 0x8c, 0xed,
+ 0x96, 0xf0, 0x6b, 0xed, 0xb6, 0x97, 0xec, 0x91, 0xbc, 0x1c,
+ 0xc6, 0xc1, 00, 0x46, 0x35, 0xe, 0xac, 0x8d, 0x67, 0x56,
+ 0xa0, 0xcd, 0x74, 0x89, 0x65, 0xe6, 0x89, 0x3d, 0x86, 0x17,
+ 0xa5, 0xdb, 0x33, 0xed, 0x5b, 0x5b, 0xbe, 0x62, 00, 0xa3,
+ 0xb2, 0x63, 0x43, 0x1a, 0x2d, 0xdf, 0x92, 0x7d, 0xd7, 0x6a,
+ 0xfe, 0x5b, 0xf3, 0xdc, 0x9a, 0xde, 0x66, 0xba, 0x84, 0x9b,
+ 0x59, 0x88, 0xe9, 0xc6, 0x26, 0xe3, 0xcc, 0xc5, 0x98, 0xbb,
+ 0x2f, 0xe4, 0xb8, 0x50, 0x74, 0xde, 0x1d, 0xeb, 0x70, 0x98,
+ 0xed, 0x72, 0xd5, 0xad, 0xb0, 0x77, 0x1f, 0x5, 0x93, 0xcc,
+ 0x23, 0xaa, 0x28, 0x95, 0xdf, 0x6c, 0x98, 0xe6, 0xb5, 0x35,
+ 0x69, 0x7d, 0x66, 0x3d, 0x37, 0x4b, 0xec, 0xc1, 0x8d, 0xe1,
+ 0xd7, 0xe0, 0x6f, 0x1e, 0x3e, 0xda, 0x5c, 0xaa, 0xbe, 0xdc,
+ 0x11, 0x75, 0xae, 0xd8, 0xad, 0x5c, 0x7e, 0x4, 0xe9, 0xe1,
+ 0x84, 0xd9, 0xbd, 0x95, 0x5f, 0x83, 0xf9, 0xd7, 0xd4, 0xc2,
+ 0xf4, 0xeb, 0x8e, 0xd5, 0x68, 0xd3, 0xdc, 0x47, 0xa9, 0x7,
+ 0x2b, 0xe1, 0xba, 0x3d, 0x21, 0xe, 0xa5, 0x1e, 0x6c, 0xb9,
+ 0x3d, 0xfc, 0x1a, 0x2c, 0xfe, 0x60, 0x78, 0x4a, 0x3d, 0x28,
+ 0x53, 0xf9, 0xc1, 0x38, 0x94, 0x7a, 0x50, 0xe9, 0x89, 0xf0,
+ 0x53, 0xfc, 0xc1, 0xdd, 0x94, 0x7a, 0xb0, 0x8b, 0xca, 0xf,
+ 0x3a, 0xa6, 0xd4, 0x83, 0x63, 0x1e, 0xa, 0x3f, 0xc5, 0x1f,
+ 0x5c, 0x4b, 0xa9, 0x7, 0x67, 0x3c, 0x57, 0xf9, 0xc9, 0x3f,
+ 0x38, 0x4f, 0xa9, 0x7, 0x97, 0xd0, 0xed, 0x9, 0x7d, 0x50,
+ 0xea, 0xc1, 0x85, 0x1e, 0xd, 0x3f, 0xc5, 0x1f, 0xec, 0xa5,
+ 0xd4, 0x83, 0x3b, 0x3c, 0x3d, 0x9e, 0x5f, 0x6b, 0xa3, 0x1d,
+ 0x41, 0xb3, 0x96, 0xb1, 0x27, 0xf9, 0xe0, 0x5a, 0xba, 0x3d,
+ 0xa1, 0x2d, 0xab, 0x52, 0xcf, 0xc9, 0x22, 0xdc, 0xe1, 0x85,
+ 0xf0, 0xd3, 0xf9, 0x9, 0x59, 0xae, 0xea, 0xc1, 0x63, 0xde,
+ 0xa9, 0xfc, 0xe4, 0x1f, 0xcc, 0x5c, 0xd5, 0x83, 0xe7, 0xbd,
+ 0xd6, 0xed, 0x29, 0xff, 0x8, 0x4e, 0xe6, 0xc1, 0x8b, 0x5c,
+ 0xf3, 0x83, 0xa7, 0xe9, 0xde, 0x84, 0xd7, 0xbd, 0x19, 0x7e,
+ 0xe5, 0xe2, 0xcf, 0x75, 0x7e, 0x6, 0xa3, 0xd4, 0x83, 0x76,
+ 0xbc, 0x5c, 0xf9, 0x6d, 0xe5, 0x9f, 0xd6, 0x81, 0x91, 0x28,
+ 0xf5, 0xa0, 0x35, 0xef, 0x77, 0x7b, 0xba, 0xf8, 0xc7, 0xa8,
+ 0x94, 0x7a, 0xd0, 0xac, 0xf7, 0xc3, 0x6f, 0x92, 0x7f, 0x8c,
+ 0x45, 0xe6, 0x41, 0xfb, 0x9a, 0x8, 0xbf, 0x49, 0xfe, 0xd1,
+ 0x3f, 0x99, 0x7, 0x1d, 0x69, 0x25, 0xfc, 0xa0, 0x5f, 0xb7,
+ 0x5e, 0xd2, 0x73, 0x5e, 0x8, 0x77, 0xf8, 0xa7, 0x9d, 0x43,
+ 0xab, 0x9d, 0x25, 0x81, 0x1a, 0x4a, 0x3d, 0xe8, 0x57, 0x5b,
+ 0x95, 0x9f, 0x46, 0x84, 0xf6, 0xc9, 0x3c, 0x18, 0x40, 0x5b,
+ 0xe1, 0xf7, 0xa1, 0xfe, 0xa3, 0x41, 0x32, 0xf, 0x46, 0xd2,
+ 0x62, 0xf8, 0xcd, 0xc3, 0x1e, 0x69, 0x65, 0x78, 0x9d, 0xcc,
+ 0x83, 0x21, 0xb5, 0x18, 0x7e, 0xd3, 0x62, 0x30, 0x17, 0x2d,
+ 0xe, 0x6f, 0x71, 0x6, 0x6, 0x3, 0x6b, 0x34, 0xfc, 0x3e,
+ 0xdc, 0x2, 0xc3, 0xf3, 0x94, 0x7a, 0x10, 0x41, 0xd3, 0xe1,
+ 0x37, 0xc9, 0x3f, 0x9e, 0x22, 0xf3, 0x20, 0x94, 0xd6, 0xc3,
+ 0x6f, 0x92, 0x7f, 0xdc, 0x49, 0xe6, 0x41, 0x4c, 0x1d, 0x84,
+ 0xdf, 0xe4, 0x16, 0x18, 0xae, 0xd6, 0x57, 0xe6, 0x39, 0xff,
+ 0x83, 0xcb, 0xf5, 0x11, 0x7e, 0x93, 0x5b, 0x60, 0xb8, 0x42,
+ 0x5f, 0x99, 0x7, 0xdc, 0xa7, 0x9b, 0xf0, 0xfb, 0x50, 0x2,
+ 0xb2, 0xd7, 0x72, 0x60, 0x48, 0xbb, 0xd, 0xf0, 0xd1, 0x59,
+ 0xf8, 0x4d, 0x4a, 0x40, 0xea, 0x28, 0xf2, 0x80, 0x82, 0xfe,
+ 0xc2, 0xef, 0x43, 0x9, 0x48, 0x96, 0xcc, 0x3, 0x6a, 0xf4,
+ 0x1a, 0x7e, 0x93, 0x12, 0x90, 0x5, 0x99, 0x7, 0xec, 0xd2,
+ 0x71, 0xf8, 0x7d, 0x28, 0x1, 0x23, 0x93, 0x79, 0xc0, 0x31,
+ 0xdd, 0x87, 0xdf, 0xb4, 0x28, 0x1, 0x27, 0x8d, 0x60, 00,
+ 0x31, 0x6f, 0x60, 0xf1, 0x6b, 0x7, 0xb8, 0xd6, 0x8, 0xe1,
+ 0xf7, 0x21, 0x2, 0xc7, 0xa6, 0xc8, 0x3, 0x2e, 0x34, 0x4e,
+ 0xf8, 0x7d, 0x88, 0xc0, 0x91, 0xc4, 0x2c, 0xf2, 0x80, 0x7,
+ 0x8c, 0x16, 0x7e, 0x1f, 0x22, 0xb0, 0x6b, 0x8a, 0x3c, 0xe0,
+ 0x6e, 0x63, 0x86, 0xdf, 0x87, 0x8, 0xec, 0x88, 0x22, 0xf,
+ 0x78, 0xd2, 0xc8, 0xe1, 0xf7, 0xb1, 0x8c, 0xc0, 0x49, 0xc3,
+ 0xda, 0x12, 0x81, 0x7, 0xbc, 0x65, 0xfc, 0xf0, 0xfb, 0x98,
+ 0xdb, 0x56, 0x85, 0xe0, 0xbb, 0x96, 0x81, 0x37, 0xd9, 0x10,
+ 0xc0, 0x4b, 0xa2, 0x84, 0xdf, 0x4c, 0x21, 0xf8, 0x3c, 0x15,
+ 0x1e, 0xd0, 0x9a, 0x70, 0xe1, 0xf7, 0xb1, 0x2a, 0x4, 0x27,
+ 0x8d, 0xf2, 0xd5, 0x4, 0xde, 0xe5, 0xfc, 0xd4, 0xf, 0x2e,
+ 0x14, 0x34, 0xfc, 0x66, 0x69, 0xa, 0x4e, 0x1a, 0xeb, 0xa3,
+ 0xac, 0x43, 0xa0, 0x17, 0xd1, 0xc3, 0x6f, 0xb6, 0x4c, 0x41,
+ 0xe5, 0x60, 0x25, 0x17, 0xf0, 0x80, 0x4e, 0x9, 0xbf, 0xb5,
+ 0x65, 0xb, 0xae, 0x94, 0x59, 0x91, 0x76, 0xc0, 0x18, 0x84,
+ 0x5f, 0xc9, 0x56, 0x10, 0xa6, 0x7f, 0x1d, 0x52, 0xc0, 0xaf,
+ 0xc, 0x4, 0x21, 0xfc, 0x6a, 0xad, 0xda, 0xfd, 0x65, 0xef,
+ 0x68, 0x76, 0x82, 0xee, 0xa4, 0x51, 0x37, 0xf5, 0xff, 0xa5,
+ 00, 0xb2, 0x84, 0xdf, 0x41, 0x69, 0x2a, 0xf4, 0x12, 0x1e,
+ 0xd9, 0xe5, 0x9c, 0x9a, 0x5c, 0x54, 0x56, 0xdc, 0xf0, 0x9,
+ 0x57, 0x11, 0x7e, 0x97, 0xc9, 0x36, 0x49, 0x5b, 0x49, 0x53,
+ 0x7e, 0xd7, 0x19, 0xcf, 0x7f, 0x22, 0x40, 0x77, 0x84, 0xdf,
+ 0xbd, 0xbe, 0x26, 0xcd, 0xd7, 0xac, 0xba, 0xfc, 0x13, 0x1,
+ 0xf8, 0x67, 0xd2, 0x97, 0xf2, 0x2a, 0xab, 0x1d, 0xe0, 0x79,
+ 0xff, 0x7b, 0x7b, 0x1, 00, 0xe0, 0x69, 0xc2, 0xf, 0x80,
+ 0x70, 0x84, 0x1f, 0xf4, 0xe4, 0x73, 0x91, 0xe2, 0xed, 0xa5,
+ 0x80, 0xee, 0x9, 0x3f, 00, 0xc2, 0x11, 0x7e, 00, 0x84,
+ 0x23, 0xfc, 00, 0x8, 0x47, 0xf8, 0x1, 0x10, 0x8e, 0xf0,
+ 0x83, 0xce, 0xb8, 0xe7, 0x5, 0xce, 0x13, 0x7e, 00, 0x84,
+ 0x23, 0xfc, 00, 0x8, 0x47, 0xf8, 0x1, 0x10, 0x8e, 0xf0,
+ 0x3, 0x20, 0x1c, 0xe1, 0x7, 0xfd, 0x71, 0xcf, 0xb, 0x9c,
+ 0x24, 0xfc, 00, 0x8, 0x47, 0xf8, 0x1, 0x10, 0x8e, 0xf0,
+ 0x3, 0x20, 0x1c, 0xe1, 0x7, 0x5d, 0x72, 0xd9, 0xf, 0xce,
+ 0x10, 0x7e, 00, 0x84, 0x23, 0xfc, 00, 0x8, 0x47, 0xf8,
+ 0x1, 0x10, 0xce, 0x9f, 0xf0, 0x73, 0xfd, 00, 0xba, 0xe3,
+ 0xb0, 0x85, 0xc3, 0x54, 0x7e, 00, 0x84, 0x23, 0xfc, 00,
+ 0x8, 0x47, 0xf8, 0x1, 0x10, 0x8e, 0xf0, 0x83, 0x8e, 0xb9,
+ 0xec, 0x7, 0xc7, 0x8, 0x3f, 00, 0xc2, 0x11, 0x7e, 00,
+ 0x84, 0x23, 0xfc, 00, 0x8, 0x47, 0xf8, 0x41, 0xdf, 0x5c,
+ 0xf6, 0x83, 0x3, 0x84, 0x1f, 00, 0xe1, 0x8, 0x3f, 00,
+ 0xc2, 0x11, 0x7e, 0xd0, 0x3d, 0x3d, 0x9f, 0xb0, 0x97, 0xf0,
+ 0x3, 0x20, 0x1c, 0xe1, 0x7, 0x40, 0x38, 0xc2, 0xf, 0x46,
+ 0xa0, 0xe7, 0x13, 0x76, 0x11, 0x7e, 00, 0x84, 0x23, 0xfc,
+ 00, 0x8, 0xe7, 0xbf, 0xf0, 0xd3, 0x6d, 0x2, 0x5d, 0x73,
+ 0x8, 0x43, 0x3d, 0x95, 0x1f, 00, 0xe1, 0x8, 0x3f, 00,
+ 0xc2, 0x11, 0x7e, 0x30, 0xe, 0x3d, 0x9f, 0x50, 0x49, 0xf8,
+ 0x1, 0x10, 0x8e, 0xf0, 0x83, 0xa1, 0x28, 0xfe, 0xa0, 0x86,
+ 0xf0, 0x3, 0x20, 0x1c, 0xe1, 0x7, 0x40, 0x38, 0xc2, 0xf,
+ 0x46, 0xa3, 0xe7, 0x13, 0xbe, 0x12, 0x7e, 00, 0x84, 0x23,
+ 0xfc, 0x60, 0x40, 0x8a, 0x3f, 0x28, 0x13, 0x7e, 00, 0x84,
+ 0x23, 0xfc, 0x60, 0x4c, 0x8a, 0x3f, 0x28, 0x10, 0x7e, 00,
+ 0x84, 0x23, 0xfc, 0x60, 0x58, 0x8a, 0x3f, 0xd8, 0x22, 0xfc,
+ 00, 0x8, 0x47, 0xf8, 0xc1, 0xc8, 0x14, 0x7f, 0x90, 0xf5,
+ 0x57, 0xf8, 0x39, 0x4e, 00, 0x88, 0x40, 0xe5, 0x7, 0x83,
+ 0x73, 0x52, 0xb, 0x29, 0xe1, 0x7, 0x40, 0x38, 0xc2, 0xf,
+ 0xc6, 0xa7, 0xf8, 0x83, 0x15, 0xe1, 0x7, 0x40, 0x38, 0xc2,
+ 0xf, 0x42, 0x50, 0xfc, 0xc1, 0x92, 0xf0, 0x83, 0x28, 0xe4,
+ 0x1f, 0xcc, 0x84, 0x1f, 00, 0xe1, 0x8, 0x3f, 0x8, 0x44,
+ 0xf1, 0x7, 0x1f, 0xc2, 0xf, 0x62, 0x91, 0x7f, 0x30, 0x9,
+ 0x3f, 00, 0x2, 0x12, 0x7e, 0x10, 0x8e, 0xe2, 0xf, 0x84,
+ 0x1f, 0x44, 0x24, 0xff, 0x8, 0x4e, 0xf8, 0x1, 0x10, 0xce,
+ 0x3a, 0xfc, 0x9c, 0xf, 0x42, 0x10, 0xe, 0x76, 0x22, 0x53,
+ 0xf9, 0x41, 0x5c, 0xf2, 0x8f, 0xb0, 0x84, 0x1f, 0x84, 0x26,
+ 0xff, 0x88, 0x49, 0xf8, 0x1, 0x10, 0x8e, 0xf0, 0x83, 0xe8,
+ 0x14, 0x7f, 0x4, 0x24, 0xfc, 00, 0xf9, 0x47, 0x38, 0xc2,
+ 0xf, 0x98, 0x26, 0xf9, 0x47, 0x30, 0xc2, 0xf, 0xf8, 0x43,
+ 0xfe, 0x11, 0x87, 0xf0, 0x3, 0xfe, 0x23, 0xff, 0x8, 0x42,
+ 0xf8, 0x1, 0x7f, 0x91, 0x7f, 0x44, 0x20, 0xfc, 0x80, 0x35,
+ 0xf9, 0xc7, 0xf0, 0x84, 0x1f, 0x90, 0x21, 0xff, 0x18, 0x9b,
+ 0xf0, 0x3, 0xf2, 0xe4, 0x1f, 0x3, 0xcb, 0x84, 0x9f, 0x3d,
+ 0x1e, 0xf8, 0xd0, 0x1a, 0x30, 0x2a, 0x95, 0x1f, 0x50, 0x22,
+ 0xff, 0x18, 0x92, 0xf0, 0x3, 0xbe, 0x90, 0x7f, 0x8c, 0x47,
+ 0xf8, 0x1, 0xdf, 0xc9, 0x3f, 0x6, 0x23, 0xfc, 0x80, 0x2a,
+ 0xf2, 0x8f, 0x91, 0x8, 0x3f, 0xa0, 0x96, 0xfc, 0x63, 0x18,
+ 0xc2, 0xf, 0xd8, 0x41, 0xfe, 0x31, 0x6, 0xe1, 0x7, 0xec,
+ 0x23, 0xff, 0x18, 0x80, 0xf0, 0x3, 0x76, 0x93, 0x7f, 0xf4,
+ 0x4e, 0xf8, 0x1, 0x47, 0x7c, 0xf2, 0x4f, 0x4, 0xd2, 0x29,
+ 0xe1, 0x7, 0x1c, 0xf4, 0xfb, 0xfb, 0xab, 0x4, 0xa4, 0x53,
+ 0xc2, 0xf, 0x38, 0x45, 0xfe, 0xd1, 0x23, 0xe1, 0x7, 0x9c,
+ 0x25, 0xff, 0xe8, 0xce, 0xcf, 0xef, 0xef, 0x6f, 0xfe, 0xf,
+ 0x3f, 0x9b, 0x7f, 0x2, 0x48, 0x7d, 0xf2, 0x4f, 0xbb, 0x41,
+ 0x17, 0x54, 0x7e, 0xc0, 0x35, 0x5c, 0x2, 0xa4, 0x23, 0xc2,
+ 0xf, 0xb8, 0x92, 0xfc, 0xa3, 0xb, 0xc2, 0xf, 0xb8, 0x98,
+ 0x5f, 0x41, 0xd0, 0x3e, 0xe1, 0x7, 0x5c, 0x4f, 0x17, 0x28,
+ 0x8d, 0x13, 0x7e, 0xc0, 0x5d, 0x94, 0x80, 0x34, 0x4b, 0xf8,
+ 0x1, 0x37, 0x52, 0x2, 0xd2, 0x26, 0xe1, 0x7, 0xdc, 0x4e,
+ 0x9, 0x48, 0x6b, 0x84, 0x1f, 0xf0, 0x4, 0x25, 0x20, 0x4d,
+ 0x11, 0x7e, 0xc0, 0x73, 0x94, 0x80, 0x34, 0x42, 0xf8, 0x1,
+ 0x8f, 0x52, 0x2, 0xd2, 0x2, 0xe1, 0x7, 0xbc, 0x40, 0x9,
+ 0xc8, 0xbb, 0xfe, 0x79, 0x7b, 0x1, 0x80, 0xa0, 0x3e, 0x4f,
+ 0x1, 0xf5, 0x44, 0x50, 0x5e, 0x51, 0x7a, 0x7a, 0xb5, 0x67,
+ 0x5b, 0x3, 0xcf, 0xd0, 0xda, 0xf0, 0x30, 0xdd, 0x9e, 0xc0,
+ 0xfb, 0xf4, 0x82, 0xf2, 0x30, 0xdd, 0x9e, 0x40, 0x13, 0xf4,
+ 0x82, 0xf2, 0x24, 0xe1, 0x7, 0x34, 0x44, 0x4, 0xf2, 0x8c,
+ 0x3e, 0xc2, 0x4f, 0x67, 0x8, 0xcf, 0xd0, 0xda, 0x36, 0x42,
+ 0x4, 0x72, 0xb7, 0x3e, 0xc2, 0x6f, 0x72, 00, 0x70, 0x3f,
+ 0xe7, 0x58, 0xad, 0x99, 0x23, 0xd0, 0xe1, 0xcf, 0xe5, 0xdc,
+ 0xf0, 0x2, 0x34, 0xcd, 0xbd, 0x30, 0xdc, 0xa1, 0x9b, 0xca,
+ 0xf, 0x8, 0x4b, 0x2f, 0x28, 0x97, 0x13, 0x7e, 0x40, 0x1f,
+ 0x44, 0x20, 0x17, 0x12, 0x7e, 0x40, 0x4f, 0x44, 0x20, 0x97,
+ 0x10, 0x7e, 0x40, 0x7f, 0x44, 0x20, 0x27, 0x9, 0x3f, 0xa0,
+ 0x57, 0x22, 0x90, 0xc3, 0x4a, 0x77, 0x7b, 0x1a, 0x76, 0x4,
+ 0x68, 0xdf, 0x3c, 0x46, 0x92, 0xf6, 0x8a, 0x7a, 0x2a, 0x3f,
+ 0x60, 0x4, 0xaa, 0x40, 0x76, 0x11, 0x7e, 0xc0, 0x38, 0x44,
+ 0x20, 0x95, 0x84, 0x1f, 0x30, 0x9a, 0x65, 0x4, 0x4e, 0x52,
+ 0x90, 0x9c, 0x28, 0xe1, 0x97, 0x9e, 0x9, 0x7a, 0x66, 0x12,
+ 0x8c, 0x6d, 0x3e, 0xc0, 0x15, 0x82, 0xa4, 0xa2, 0x84, 0xdf,
+ 0x6a, 0xbf, 0x77, 0x61, 0x1c, 0xe2, 0xd0, 0x17, 0x4a, 0x2a,
+ 0x4a, 0xf8, 0xa5, 0x1c, 0x3, 0x10, 0x8a, 0x8, 0x64, 0xa9,
+ 0xef, 0xf0, 0x5b, 0x15, 0x70, 0xe9, 0x6f, 0x33, 0xb2, 0xbb,
+ 0xbb, 0xe, 0x4f, 0x8, 0x4b, 0x4, 0xf2, 0xd1, 0x71, 0xf8,
+ 0x2d, 0x77, 0xdf, 0x55, 0x9e, 0xad, 0x2e, 0x77, 0x3, 0x2c,
+ 0x89, 0x40, 0x3a, 0xe, 0xbf, 0xe9, 0xd0, 0x5e, 0xab, 0xec,
+ 0x3, 0x3e, 0x44, 0x60, 0x64, 0xbd, 0x86, 0xdf, 0x32, 0xc3,
+ 0xb2, 0x5d, 0x9d, 0x2b, 0x6a, 0x41, 0x20, 0x4b, 0x4, 0xc6,
+ 0xf4, 0x65, 0x30, 0xdb, 0xf6, 0x9f, 0x70, 0xb6, 0xb5, 0xcb,
+ 0x6e, 0x55, 0x78, 0x76, 0x6e, 0x20, 0xe5, 0x19, 0x69, 0xd1,
+ 0xf4, 0x5a, 0xf9, 0x4d, 0x8b, 0xd8, 0xfb, 0xec, 0xaf, 0x73,
+ 0x4e, 0x17, 0xe2, 0xf0, 0xf9, 0x85, 0x4, 0x3a, 0xa2, 0xa,
+ 0x8c, 0xa3, 0xd7, 0xf0, 0x4b, 0x6f, 0x6f, 0xd9, 0xfa, 0xef,
+ 0xfc, 0x8a, 0x5d, 0x19, 0xa8, 0x21, 0x2, 0x23, 0xe8, 0x35,
+ 0xfc, 00, 0x6e, 0x25, 0x2, 0xc7, 0xf6, 0xe5, 0x9a, 0x5f,
+ 0x77, 0xec, 0xa3, 0xc0, 0x85, 0xe6, 0x6b, 0x81, 0x6f, 0x2f,
+ 0x8, 0x17, 0x1b, 0x2a, 0xfc, 0x24, 0x1f, 0x70, 0x7, 0xf7,
+ 0xc2, 0x8c, 0x67, 0xa8, 0xf0, 0x3, 0xb8, 0x89, 0x12, 0x70,
+ 0x30, 0xc2, 0xf, 0xa0, 0x96, 0x12, 0x70, 0x18, 0xc2, 0xf,
+ 0x60, 0x7, 0x25, 0xe0, 0x18, 0x84, 0x5f, 0x5e, 0x61, 0xcf,
+ 0x5e, 0xfe, 0x69, 0xfe, 0xb7, 0x23, 0x1, 0x42, 0x51, 0x2,
+ 0xf6, 0x4e, 0xf8, 0xe5, 0x55, 0xde, 0x3b, 0xe3, 0x16, 0x1b,
+ 0x8, 0x4b, 0x9, 0xd8, 0xb5, 0xaa, 0xf0, 0x1b, 0x7e, 0xeb,
+ 0xe, 0xff, 0x5, 0x81, 0x9b, 0xc8, 0xbf, 0x4e, 0x7d, 0xff,
+ 0x91, 0xfb, 0x90, 0x9b, 0x76, 0xfe, 0x46, 0xe9, 0xd3, 0xb1,
+ 0xe7, 0xef, 0xfb, 0xb5, 0xaa, 0x4b, 0x87, 0x9, 0x5c, 0xcd,
+ 0x73, 0xf5, 0x7a, 0xcd, 0x3c, 0x81, 0xee, 0x7c, 0x1a, 0xd,
+ 0x47, 0x77, 0x5f, 0x82, 0x76, 0x7b, 0x7e, 0xfa, 0x2b, 0xb2,
+ 0xaf, 0xd4, 0xef, 0xc4, 0x85, 0x39, 0xcc, 0x2f, 0x7e, 0xe6,
+ 0x36, 0xbb, 0x60, 0xd1, 0x81, 0xf6, 0xb8, 0x4, 0xd8, 0x9d,
+ 0xa0, 0xe1, 0xb7, 0xb5, 0x8f, 0x9e, 0xcf, 0x27, 0x9, 0x7,
+ 0x31, 0xb9, 0x4, 0xd8, 0x97, 0x88, 0xe1, 0x77, 0xeb, 0xde,
+ 0x99, 0xce, 0xdc, 0x1d, 0xa1, 00, 0xad, 0x89, 0x18, 0x7e,
+ 0xcb, 0xce, 0xc9, 0x65, 0x32, 0xcd, 0x43, 0x23, 0x1d, 0x9b,
+ 0xed, 0xdc, 0xe9, 0x91, 0x3e, 0xf, 0xf7, 0xe4, 0x9c, 0x81,
+ 0x5e, 0x28, 0xfe, 0x7a, 0x51, 0xd5, 0x22, 0xbf, 0xde, 0x70,
+ 0xdf, 0xbd, 00, 0xaf, 0x7f, 0x41, 0x5a, 0x60, 0x37, 0xe0,
+ 0x2a, 0xf6, 0xa5, 0xf6, 0x19, 0xd2, 0xa8, 0x24, 0x3d, 0x83,
+ 0xb3, 0x43, 0x3, 0x5f, 0xb9, 0xff, 0xb3, 0x7d, 0x11, 0xbb,
+ 0x3d, 0x57, 0xa, 0x7d, 0x14, 0xbf, 0x89, 0x27, 0x17, 0xc,
+ 0xae, 0x72, 0x6d, 0x47, 0x5c, 0xe1, 0xc2, 0xf6, 0x3, 0x8b,
+ 0xa1, 0x53, 0x91, 0x4b, 0x8, 0xbf, 0xcc, 0xcf, 0x1e, 0x80,
+ 0x82, 0xf4, 0xb7, 0xad, 0x5, 0x63, 0x64, 0xd5, 0x81, 0x6f,
+ 0xe1, 0xe2, 0x5f, 0xe3, 0x84, 0x1f, 0x8c, 0xe0, 0xf9, 0x76,
+ 0xf6, 0x92, 0xe4, 0x7b, 0x66, 0xb1, 0x8f, 0x95, 0xaa, 0xee,
+ 0xd3, 0x1e, 0x5b, 0xd5, 0x35, 0x3f, 0xfd, 0xd7, 0x70, 0xad,
+ 0xd5, 0x73, 0x7f, 0xe6, 0x7b, 0x83, 0x3f, 0x7, 0x5a, 0xcd,
+ 0x53, 0x81, 0xb2, 0x4f, 0x14, 0x2a, 0xbc, 0x7d, 0xef, 0x13,
+ 0x88, 0xe6, 0x43, 0x7e, 0xf5, 0x8f, 0xad, 0xe7, 0x1f, 0x6d,
+ 0xcd, 0xff, 0xf0, 0x62, 0xaf, 0xa6, 0xdc, 0x4a, 0xa0, 0x74,
+ 0xf9, 0xb3, 0xcb, 0x59, 0x7e, 0xa8, 0x53, 0x79, 0x3d, 0x14,
+ 0xbe, 0x4e, 0x99, 0x96, 0xb3, 0x65, 0x6e, 0x78, 0x81, 0xd7,
+ 0x94, 0x9b, 0xc5, 0x9a, 0xbf, 0xae, 0x9a, 0xe6, 0x42, 0x6b,
+ 0x9b, 0x9d, 0xfe, 0x40, 0xd3, 0xbc, 0x8a, 0xea, 0x9a, 0xe5,
+ 0xa9, 0x5c, 0xec, 0xc2, 0x2, 0x2f, 0x97, 0x33, 0x9b, 0x46,
+ 0xe9, 0xb7, 0xd8, 0x5a, 0xbc, 0x79, 0x56, 0xcb, 0x57, 0xa6,
+ 0xbf, 0x43, 0x71, 0xf9, 0x71, 0xe5, 0xe8, 0xa5, 0x5f, 0xba,
+ 0x3d, 0xf3, 0xec, 0xeb, 0xdc, 0x6a, 0xab, 0xe5, 0xcd, 0xfe,
+ 0x35, 0xeb, 0xee, 0x5d, 0x74, 0xf9, 0xbc, 0xae, 0xc7, 0x7e,
+ 0xa8, 0xba, 0xbc, 0xb3, 0xac, 0xf2, 0xb, 0xd6, 0xac, 0xab,
+ 0xd5, 0xc4, 0x7b, 0x5f, 0x61, 0x48, 0xc2, 0x2f, 0xcf, 0x1,
+ 0xc0, 0xad, 0x7e, 0xfe, 0x7d, 0xe8, 0x6b, 0xfa, 0xe2, 0xd6,
+ 0x5f, 0x57, 0x53, 0x96, 0x67, 0x5e, 0x33, 0x59, 0xe5, 0xc4,
+ 0xcf, 0x1f, 0xb, 0xd9, 0x24, 0x2b, 0x74, 0x7b, 0x5e, 0x72,
+ 0xcf, 0x9a, 0x2b, 0x7c, 0xd1, 0x8, 0xbf, 0x69, 0xb2, 0xbb,
+ 0xf3, 0x86, 0x55, 0x13, 0x9f, 0x6, 0x61, 0xf9, 0x47, 0x38,
+ 0x53, 0xee, 0x29, 0x45, 0x53, 0xae, 0x7f, 0x6f, 0xeb, 0xd3,
+ 0x6b, 0x26, 0x5e, 0xf5, 0xfe, 0x6d, 0xcd, 0xa7, 0xac, 0x26,
+ 0xaa, 0x57, 0x4b, 0x92, 0xed, 0xf3, 0x5c, 0x56, 0xa2, 0xab,
+ 0x39, 0x54, 0xbe, 0xb2, 0xea, 0x3e, 0x4d, 0x3f, 0x2e, 0xed,
+ 0x2, 0xdd, 0xf5, 0x4d, 0x77, 0x7d, 0x71, 0xde, 0x55, 0xdb,
+ 0x95, 0xf1, 0x4c, 0xa7, 0xc7, 0x63, 0x9f, 0x3e, 0xef, 0x94,
+ 0xd9, 0x6b, 0xdd, 0xd9, 0x9e, 0xa8, 0xd5, 0xc2, 0x64, 0x2f,
+ 0x51, 0x64, 0xe7, 0xb3, 0x7c, 0x25, 0x5d, 0x80, 0xc2, 0x7,
+ 0xf1, 0xb0, 0xc1, 0x76, 0x72, 0x66, 0xe9, 0xba, 0x7d, 0x66,
+ 0x6d, 0xdb, 0xa6, 0x2d, 0xb, 0x7a, 0xc3, 0xcb, 0xd6, 0xfd,
+ 0x5d, 0xf3, 0x99, 0xe0, 0xd7, 0x53, 0xb6, 0xd5, 0x9d, 0x5,
+ 0xd9, 0x59, 0x2d, 0xff, 0x9d, 0xbd, 0x8f, 0xe, 0xa6, 0x8a,
+ 0xfd, 0x21, 0x7b, 0xa6, 0x75, 0xe7, 0x12, 0xc1, 0xf8, 0x82,
+ 0x86, 0x5f, 0xa1, 0x93, 0xe7, 0x4c, 0x4f, 0xc5, 0xf2, 0x1e,
+ 0x81, 0x93, 0xb3, 0x22, 0x94, 0x72, 0xfe, 0x89, 0xba, 0x33,
+ 0xea, 0x2f, 0x1f, 0x5e, 0xfe, 0xb9, 0x36, 0x5c, 0xcb, 0x22,
+ 0x86, 0xdf, 0x7d, 0xbb, 0xfe, 0xf2, 0xe2, 0xc4, 0xf2, 0xb3,
+ 0xb2, 0x3f, 0x8a, 0xca, 0x16, 0x85, 0x4, 0x64, 0x7, 0xb8,
+ 0xd5, 0x2b, 0xf7, 0x73, 0x3a, 0xae, 0xdb, 0x57, 0x7b, 0xc3,
+ 0xcb, 0x48, 0x75, 0xcc, 0xd6, 0xcd, 0x2, 0x5f, 0xef, 0x11,
+ 0xd8, 0x7a, 0xd7, 0x6a, 0x82, 0xc2, 0x99, 0xe6, 0xae, 0x5b,
+ 0x12, 0x80, 0x1e, 0x39, 0xae, 0xbb, 0xb0, 0x63, 0x23, 0xbd,
+ 0xb8, 0x45, 0xef, 0xfe, 0xe8, 0x5b, 0xe7, 0xbf, 0xba, 0xb9,
+ 0x86, 0x66, 0x69, 0xb3, 0x38, 0xa9, 0x7c, 0xaf, 0x1c, 0x4d,
+ 0x89, 0xd8, 0xed, 0x59, 0xef, 0xcc, 0x8d, 0x6, 0x73, 0x4b,
+ 0x5a, 0x78, 0xe8, 0x6, 0x30, 0x6, 0xb1, 0xd7, 0x1d, 0xe1,
+ 0x57, 0xba, 0x4, 0x78, 0x66, 0x57, 0xfe, 0x4d, 0x1e, 0x4e,
+ 0xd8, 0x11, 0x69, 0xd, 0x95, 0xfa, 0x3d, 0xcc, 0x83, 0x13,
+ 0x7e, 0x37, 0xee, 0xb2, 0x3, 0x1f, 0xc, 0xd2, 0x11, 0x54,
+ 0x7b, 0x5d, 0x13, 0x7e, 0xec, 0x36, 0xcc, 0xad, 0x4f, 0x70,
+ 0x80, 0x52, 0x6f, 0xc, 0xc2, 0x6f, 0x7c, 0x85, 0xe7, 0xce,
+ 0x6c, 0xfd, 0xd8, 0x7f, 0x7e, 0x63, 0xf6, 0x57, 0xfc, 0x5b,
+ 0x73, 0xae, 0xfc, 0x13, 0xf4, 0x48, 0xe6, 0xd, 0x46, 0xf8,
+ 0x45, 0x91, 0xfe, 0xac, 0x30, 0x7d, 0x92, 0xe1, 0x52, 0x21,
+ 0xf9, 0xb2, 0x9, 0xba, 0xf5, 0x5e, 0xe8, 0x9a, 0xcc, 0x1b,
+ 0xd5, 0x8e, 0xf0, 0x73, 0xd7, 0x62, 0xa7, 0x96, 0xcf, 0x9d,
+ 0x49, 0x5f, 0x2f, 0xbc, 0x71, 0xb5, 0xb9, 0xb3, 0x3f, 0x16,
+ 0x2e, 0x27, 0x28, 0xf4, 0x48, 0xbf, 0x45, 0x4, 0x46, 0x75,
+ 0x18, 0xdf, 0xcf, 0xdf, 0x63, 0xbe, 0xac, 0x7e, 0x71, 0x9f,
+ 0xfd, 0xc7, 0x54, 0xf7, 0x14, 0xff, 0xd5, 0x9c, 0xb3, 0x93,
+ 0xb9, 0x40, 0x48, 0x2f, 0xe6, 0x27, 0x5d, 0x4c, 0x7f, 0x8f,
+ 0x2c, 0xc8, 0x90, 0xf6, 0x55, 0x72, 0x6f, 0x55, 0x7e, 0x4f,
+ 0xfe, 0xc8, 0x7d, 0xbc, 0xea, 0xb6, 0xfe, 0x9a, 0xdf, 0xd7,
+ 0xe7, 0x74, 0xa7, 0xff, 0x4d, 0x27, 0xdb, 0x9a, 0x67, 0xfb,
+ 0xc6, 0xdb, 0xf4, 0xd4, 0xe8, 0x71, 0x5f, 0xe5, 0xbc, 0xa0,
+ 0xd7, 0xfc, 0xb2, 0x25, 0x4e, 0x21, 0x2, 0xbb, 0xee, 0x6,
+ 0x59, 0x2d, 0x70, 0xcd, 0xa3, 0xe, 0xbf, 0xbe, 0xb2, 0xb5,
+ 0x12, 0xe6, 0xd7, 0xbb, 0x5b, 0x4b, 0x84, 0xd2, 0xf5, 0x11,
+ 0xcd, 0x25, 0x22, 0x86, 0xdf, 0x56, 0x47, 0xdc, 0xd6, 0xf5,
+ 0x2d, 0x5, 0x1, 0x8c, 0x41, 0x91, 0xc7, 0x2c, 0x62, 0xf8,
+ 0x7d, 0xd8, 0xfb, 0x21, 0x2, 0x45, 0x1e, 0x59, 0x71, 0xc3,
+ 0xef, 0xa3, 0xb2, 0xaa, 0x33, 0x2, 0x11, 0x74, 0x44, 0xe0,
+ 0xf1, 0x55, 0xc4, 0xf0, 0xcb, 0xde, 0xa0, 0x9f, 0xbd, 0xe0,
+ 0x37, 0xdf, 0xcd, 0xe8, 0x86, 0x7e, 0x68, 0x9f, 0x5e, 0x4d,
+ 0xea, 0xed, 0xae, 0x63, 0x5e, 0x29, 0x7d, 0xd4, 0x5b, 0x3c,
+ 0xc0, 0x6e, 0xd6, 0x29, 0x99, 0xc7, 0x1, 0x11, 0x2b, 0x3f,
+ 0xa0, 0x77, 0x3a, 0x36, 0x39, 0x49, 0xf8, 0x1, 0xdd, 0x50,
+ 0xe4, 0x71, 0x15, 0xe1, 0x7, 0xb4, 0x4e, 0x9d, 0xc7, 0xe5,
+ 0x84, 0x1f, 0xd0, 0x28, 0x75, 0x1e, 0xf7, 0x11, 0x7e, 0x40,
+ 0x5b, 0x64, 0x1e, 0xf, 0x10, 0x7e, 0x40, 0x2b, 0xfc, 0xa0,
+ 0x88, 0xc7, 0xec, 0xe, 0xbf, 0x68, 0x3, 0x1b, 0x85, 0xfa,
+ 0xb2, 0xf0, 0xa, 0xa5, 0x1e, 0xcf, 0xb, 0x5a, 0xf9, 0xd5,
+ 0x47, 0x9a, 0xa3, 0x11, 0xee, 0xa3, 0xd4, 0xe3, 0x2d, 0x11,
+ 0xc3, 0xaf, 0x30, 0xc2, 0x5c, 0x39, 0x14, 0x55, 0x81, 0x70,
+ 0x9, 0xa5, 0x1e, 0xaf, 0x8b, 0x18, 0x7e, 0x4b, 0xe5, 0x81,
+ 0xeb, 0xd2, 0xd3, 0xd2, 0xad, 0x83, 0xd6, 0xad, 0xd8, 0x50,
+ 0x43, 0xa9, 0x47, 0x23, 0x22, 0x86, 0xdf, 0x9c, 0x6a, 0xd9,
+ 0x4a, 0x6e, 0x8e, 0xc0, 0xcf, 0x5f, 0x57, 0x65, 0xe2, 0xea,
+ 0xaf, 0x9f, 0x17, 0x55, 0x84, 0xf0, 0x95, 0xd8, 0xa3, 0x29,
+ 0xff, 0x7b, 0x7b, 0x1, 0x1a, 0x55, 0x3e, 0x44, 0x1d, 0xc0,
+ 0x50, 0x6f, 0x3e, 0x59, 0x74, 0xe0, 0xd0, 0x8e, 0x23, 0xe1,
+ 0x97, 0xd6, 0x43, 0xfd, 0x9a, 0xbf, 0xc8, 0xc9, 0x6f, 0x74,
+ 0xd5, 0x7c, 0x60, 0x24, 0x62, 0x8f, 0x66, 0x45, 0xec, 0xf6,
+ 0xfc, 0x98, 0x7b, 0x35, 0xd3, 0xb1, 0x8d, 0x3e, 0xff, 0xc8,
+ 0x1e, 0xae, 0xab, 0xbf, 0x1a, 0xf3, 0x8, 0xb2, 0x1c, 0xe,
+ 0x34, 0x2e, 0x68, 0xf8, 0xcd, 0xc7, 0xe4, 0xd6, 0x35, 0xbf,
+ 0xbd, 0xff, 0x75, 0x90, 0xc3, 0xcc, 0x55, 0x70, 0xda, 0x17,
+ 0x34, 0xfc, 0x80, 0x3b, 0x28, 0xf8, 0xe8, 0x85, 0xf0, 0xfb,
+ 0x4f, 0xf9, 0x72, 0x9d, 0x8b, 0x79, 0x50, 0xa6, 0xe0, 0xa3,
+ 0x23, 0x7, 0xc3, 0x6f, 0xc8, 0x87, 0x9c, 0xb9, 0xc3, 0x13,
+ 0x8e, 0x51, 0xf0, 0xd1, 0x1d, 0x95, 0x1f, 0x70, 0xca, 0x78,
+ 0xe7, 0xc1, 0x44, 0x20, 0xfc, 0x80, 0x83, 0x14, 0x7c, 0xf4,
+ 0x4b, 0xf8, 0x1, 0x47, 0x28, 0xf8, 0xe8, 0x9a, 0x27, 0xbc,
+ 00, 0xbb, 0x49, 0x3e, 0x7a, 0x77, 0x3c, 0xfc, 0x46, 0x7a,
+ 0xce, 0xb, 0x50, 0x4f, 0xf2, 0x31, 00, 0xdd, 0x9e, 0x40,
+ 0x2d, 0x17, 0xf9, 0x18, 0x86, 0xf0, 0x3, 0xaa, 0x28, 0xf8,
+ 0x18, 0x89, 0x6b, 0x7e, 0xc0, 0x77, 0x92, 0x8f, 0xc1, 0x8,
+ 0x3f, 0xe0, 0xb, 0xc9, 0xc7, 0x78, 0x4e, 0x85, 0x9f, 0x7b,
+ 0x5e, 0x60, 0x78, 0x92, 0x8f, 0x21, 0xa9, 0xfc, 0x80, 0x4d,
+ 0x92, 0x8f, 0x51, 0x9, 0x3f, 0x20, 0x4f, 0xf2, 0x31, 0x30,
+ 0x77, 0x7b, 0x2, 0x6b, 0x7e, 0xd2, 0xc0, 0xf0, 0x84, 0x1f,
+ 0xf0, 0x17, 0x5, 0x1f, 0x11, 0x9c, 0xed, 0xf6, 0x74, 0xcf,
+ 0xb, 0x8c, 0x44, 0xf2, 0x11, 0x84, 0x6b, 0x7e, 0xc0, 0x1f,
+ 0x92, 0x8f, 0x38, 0x84, 0x1f, 0x30, 0x4d, 0x92, 0x8f, 0x60,
+ 0x84, 0x1f, 0x20, 0xf9, 0x8, 0xe7, 0x82, 0xf0, 0x73, 0xd9,
+ 0xf, 0x7a, 0x27, 0xf9, 0x88, 0x46, 0xe5, 0x7, 0xa1, 0x39,
+ 0x73, 0x25, 0x26, 0xe1, 0x7, 0x71, 0xe9, 0xed, 0x24, 0xac,
+ 0x6b, 0xc2, 0x4f, 0xcf, 0x27, 0x74, 0x47, 0xf2, 0x71, 0x46,
+ 0xef, 0x6d, 0xbe, 0x1f, 0xb9, 0x43, 0x44, 0xc7, 0x92, 0x6f,
+ 0x6e, 0xef, 0x56, 0xef, 0xdd, 0x7a, 0x3d, 0xfb, 0xf6, 0x79,
+ 0x9a, 0x79, 0x19, 0x2a, 0x1f, 0x28, 0xb3, 0x5c, 0xe6, 0x5b,
+ 0x9f, 0x41, 0x53, 0x3f, 0xf3, 0xec, 0x94, 0xbb, 0x96, 0x2d,
+ 0x9d, 0x78, 0x15, 0x2a, 0x7b, 0xbf, 0xe3, 0xd6, 0x4a, 0xae,
+ 0x5f, 0xb0, 0xc2, 0x2, 0xac, 0xfe, 0xd4, 0xe0, 0xf9, 0x53,
+ 0xfd, 0x22, 0xe9, 0xf6, 0x84, 0x70, 0xce, 0xb7, 0x59, 0xbd,
+ 0x9f, 0xf5, 0xb7, 0xef, 0xf7, 0xf7, 0x77, 0x79, 0x66, 0xf0,
+ 0x98, 0x39, 0x20, 0xd3, 0x5, 0x58, 0xfd, 0xa9, 0xb5, 0xd8,
+ 0xdb, 0x4b, 0xf8, 0x41, 0x2c, 0x27, 0x93, 0x2f, 0x7d, 0xef,
+ 0xc9, 0x22, 0x72, 0x5a, 0x34, 0xf4, 0x95, 0xd3, 0x53, 0xb0,
+ 0x5c, 0x99, 0x7b, 0x57, 0xda, 0x56, 0x69, 0xb8, 0x9c, 0xcf,
+ 0x6a, 0xc3, 0x1d, 0x5c, 0xca, 0x7b, 0xec, 0xfa, 0xbe, 0x97,
+ 0x75, 0x7b, 0x7e, 0x2e, 0xfb, 0xdd, 0xb7, 0x2e, 0xec, 0xfa,
+ 0x70, 0xde, 0x33, 0xfd, 0x54, 0xcb, 0x36, 0xb4, 0xd0, 0x31,
+ 0x38, 0x2f, 0xcf, 0xd7, 0xee, 0xb8, 0xd5, 0xf4, 0xe9, 0xeb,
+ 0xab, 0x8f, 0x5b, 0xbe, 0x58, 0x33, 0x4d, 0xfa, 0x62, 0xfd,
+ 0x47, 0x94, 0x65, 0x57, 0xc5, 0xc9, 0xad, 0x50, 0x9e, 0xe7,
+ 0xf2, 0x95, 0x79, 0xfa, 0xf2, 0x4a, 0x2b, 0xc8, 0xde, 0xcf,
+ 0x51, 0xd8, 0x5e, 0xab, 0x99, 0x6f, 0xed, 0x9, 0x5b, 0x3d,
+ 0xab, 0xbb, 0x5e, 0x2f, 0x6c, 0xb2, 0x9a, 0xd5, 0xdb, 0xc7,
+ 0x35, 0xbf, 0xd6, 0xce, 0x2f, 0xa0, 0x47, 0x57, 0x25, 0xdf,
+ 0xa7, 0x51, 0x9b, 0x73, 0xeb, 0xc0, 0x3c, 0x6b, 0x2, 0xaf,
+ 0x66, 0xfa, 0xad, 0x46, 0x30, 0x7d, 0x7d, 0xb9, 0xcc, 0xab,
+ 0x79, 0x4e, 0x49, 0x6b, 0x9e, 0x9d, 0xe1, 0xe7, 0xed, 0xcb,
+ 0xf9, 0x67, 0xa7, 0xbc, 0x4a, 0xe5, 0x65, 0xd4, 0x82, 0xbd,
+ 0x2b, 0xad, 0x66, 0x86, 0xd3, 0xf6, 0x89, 0x48, 0x3a, 0x65,
+ 0xfd, 0xc, 0x57, 0xb3, 0x5a, 0xbd, 0x9e, 0xa6, 0xe6, 0x6a,
+ 0x3b, 0xce, 0xaf, 0xec, 0xda, 0xa9, 0xfa, 0x8, 0x3f, 0xe0,
+ 0xa4, 0x3b, 0x6a, 0xbe, 0xcb, 0x9b, 0xfe, 0xad, 0x19, 0x1e,
+ 0x5b, 0xf2, 0x34, 0xde, 0x96, 0xaf, 0xd7, 0x2c, 0x7c, 0xf6,
+ 0xed, 0x7, 0x96, 0x61, 0xab, 0xdb, 0xb0, 0xfc, 0xc6, 0xcb,
+ 0xe7, 0x79, 0x89, 0xad, 0x10, 0x5a, 0xba, 0xaf, 0x83, 0x21,
+ 0x5b, 0x89, 0x4e, 0x87, 0xf6, 0x90, 0x2b, 0xc3, 0xef, 0xee,
+ 0x9e, 0x4f, 0xe0, 0x98, 0x5b, 0x1b, 0xa3, 0x66, 0xe7, 0xb6,
+ 0x35, 0xe7, 0xb4, 0x63, 0xb0, 0xfe, 0xed, 0x67, 0x62, 0x66,
+ 0x6f, 0x69, 0xf2, 0xd6, 0x3c, 0xb7, 0x6c, 0xd5, 0xcd, 0xd9,
+ 0xe5, 0x69, 0x3f, 0xb, 0xdc, 0xf0, 0x2, 0x83, 0xbb, 0xa3,
+ 0x19, 0x6a, 0xbc, 0x5d, 0x9b, 0xa5, 0xd7, 0x1a, 0x2b, 0xaf,
+ 0x57, 0x6d, 0xbd, 0x7d, 0x6b, 0xca, 0xbd, 0x4b, 0x72, 0x89,
+ 0x9b, 0x36, 0x6b, 0x5a, 0x53, 0x56, 0x66, 0xff, 0x3c, 0xf1,
+ 0x1d, 0x5f, 0xf6, 0xf2, 0xea, 0x56, 0xf8, 0xc1, 0xc8, 0x2e,
+ 0x4c, 0xbe, 0xf9, 0x8c, 0x7e, 0x7e, 0x25, 0x6d, 0x13, 0x57,
+ 0xed, 0x66, 0xb6, 0xc1, 0x3a, 0xd3, 0x5f, 0x57, 0x39, 0x7d,
+ 0xf6, 0x1e, 0x8d, 0x9f, 0xbf, 0x7f, 0xf1, 0xb6, 0xf5, 0x45,
+ 0xb6, 0x96, 0xf9, 0xf3, 0xf6, 0xaf, 0x53, 0xa6, 0xcb, 0x90,
+ 0xbd, 0xe4, 0xb6, 0x9a, 0xa6, 0xf0, 0x8f, 0xac, 0xc2, 0x3c,
+ 0xb, 0x4b, 0x52, 0x63, 0x79, 0xbd, 0x2d, 0x7b, 0xa2, 0x50,
+ 0xf8, 0xd3, 0xf2, 0xaf, 0xab, 0xaf, 0x59, 0x58, 0xab, 0x5b,
+ 0x1f, 0x31, 0xbf, 0xbe, 0x5a, 0xe7, 0xab, 0x70, 0xcd, 0x6e,
+ 0xeb, 0x9a, 0x6f, 0x7a, 0xf1, 0x29, 0xe1, 0x63, 0x5, 0x38,
+ 0xf0, 0x55, 0xfb, 0x5d, 0x4f, 0xc4, 0x54, 0xc8, 0xce, 0xec,
+ 0xeb, 0x77, 0xb8, 0xb8, 0xf2, 0x73, 0xa4, 0x41, 0x23, 0x24,
+ 0x1f, 0x14, 0xe8, 0xf6, 0x84, 0x1, 0x49, 0x3e, 0x9a, 0xb5,
+ 0xd5, 0x2d, 0xf9, 0xe4, 0x3d, 0xab, 0x93, 0x9f, 0x3a, 0xc0,
+ 0x78, 0x24, 0x1f, 0x2d, 0x3b, 0xf9, 0xeb, 0xc0, 0xab, 0x5c,
+ 0x5f, 0xf9, 0xed, 0xba, 0x81, 0x18, 0xb8, 0x96, 0xe4, 0x83,
+ 0x1a, 0xba, 0x3d, 0x61, 0x1c, 0x92, 0xf, 0x2a, 0x9, 0x3f,
+ 0x18, 0x84, 0xe4, 0x83, 0x7a, 0xb7, 0x84, 0x9f, 0x9e, 0x4f,
+ 0x78, 0x98, 0xe4, 0x83, 0x5d, 0x54, 0x7e, 0xd0, 0x3d, 0xc9,
+ 0x7, 0x7b, 0xdd, 0x15, 0x7e, 0x8a, 0x3f, 0x78, 0x86, 0xe4,
+ 0x83, 0x3, 0x54, 0x7e, 0xd0, 0x31, 0xc9, 0x7, 0xc7, 0x8,
+ 0x3f, 0xe8, 0x95, 0xe4, 0x83, 0xc3, 0x6e, 0xc, 0x3f, 0x3d,
+ 0x9f, 0x70, 0x1f, 0xc9, 0x7, 0x67, 0xa8, 0xfc, 0xa0, 0x3f,
+ 0x92, 0xf, 0x4e, 0xba, 0x37, 0xfc, 0x14, 0x7f, 0x70, 0x39,
+ 0xc9, 0x7, 0xe7, 0xa9, 0xfc, 0xa0, 0x27, 0x92, 0xf, 0x2e,
+ 0x21, 0xfc, 0xa0, 0x1b, 0x92, 0xf, 0xae, 0x72, 0x7b, 0xf8,
+ 0xe9, 0xf9, 0x84, 0x4b, 0x48, 0x3e, 0xb8, 0x90, 0x21, 0x8d,
+ 0xa0, 0x75, 0x4f, 0xe, 0x6f, 0xd, 0x41, 0x3c, 0x74, 0x2e,
+ 0xe9, 0xa4, 0x15, 0x8e, 0x71, 0xec, 0xc0, 0x1d, 0x5c, 0xf3,
+ 0x83, 0x76, 0x49, 0x3e, 0xb8, 0xc9, 0x43, 0xe1, 0xe7, 0xca,
+ 0x1f, 0xec, 0x25, 0xf9, 0xe0, 0x3e, 0x2a, 0x3f, 0x68, 0x91,
+ 0xe4, 0x83, 0x5b, 0x3d, 0x17, 0x7e, 0x8a, 0x3f, 0xa8, 0x24,
+ 0xf9, 0xe0, 0x6e, 0xee, 0xf6, 0x84, 0x86, 0xb8, 0xb1, 0x13,
+ 0x9e, 0xf1, 0xf4, 0x9, 0xa6, 0x53, 0x5a, 0xd8, 0xe2, 0xe8,
+ 0x80, 0xc7, 0xb8, 0xe6, 0x7, 0x4d, 0x90, 0x7c, 0xf0, 0xa4,
+ 0xa7, 0xc3, 0xcf, 0x95, 0x3f, 0x48, 0x49, 0x3e, 0x78, 0xd8,
+ 0x3b, 0x87, 0x9c, 0x43, 0x1d, 0x3e, 0x5c, 0xe4, 0x83, 0x57,
+ 0xb8, 0xe1, 0x5, 0x5e, 0xe3, 0x2c, 0x10, 0xde, 0xf2, 0xce,
+ 0x35, 0x3f, 0x9d, 0x9f, 0x20, 0xf9, 0xe0, 0x45, 0x6e, 0x78,
+ 0x81, 0x17, 0x48, 0x3e, 0x78, 0xd7, 0x9b, 0x47, 0xa0, 0xe3,
+ 0x9f, 0x80, 0x5c, 0xe4, 0x83, 0x16, 0xbc, 0x1c, 0x3f, 0xf2,
+ 0x8f, 0x50, 0xec, 0xf0, 0xd0, 0x8, 0x37, 0xbc, 0xc0, 0x13,
+ 0x14, 0x7c, 0xd0, 0x94, 0xf7, 0xcf, 0x43, 0x9d, 0xb, 0x33,
+ 0x3c, 0x3b, 0x39, 0xb4, 0xe6, 0xfd, 0x1b, 0x5e, 0xdc, 0xf9,
+ 0xc9, 0xd8, 0x24, 0x1f, 0x34, 0x48, 0xb7, 0x27, 0xdc, 0x45,
+ 0x57, 0x27, 0x34, 0xab, 0x95, 0x73, 0x52, 0x67, 0xc7, 0xc,
+ 0xc6, 0x2e, 0xd, 0x2d, 0x6b, 0xe8, 0xf8, 0xd4, 0x58, 0x30,
+ 0x6, 0x5, 0x1f, 0xb4, 0xaf, 0xad, 0xbc, 0x91, 0x7f, 0xf4,
+ 0xce, 0x3e, 0xc, 0x5d, 0x70, 0xcd, 0xf, 0xae, 0xa1, 0xe0,
+ 0x83, 0x8e, 0x34, 0x77, 0x96, 0xea, 0xc4, 0x99, 0x1e, 0xd9,
+ 0x6f, 0xa1, 0x2f, 0x2d, 0x1e, 0xb1, 0xda, 0x11, 0x3a, 0xa2,
+ 0xe0, 0x83, 0x1e, 0x35, 0x1a, 0x33, 0xf2, 0x8f, 0xf6, 0x89,
+ 0x3d, 0xe8, 0x57, 0xbb, 0x19, 0x23, 0xff, 0x68, 0x99, 0xfd,
+ 0x13, 0xba, 0xd6, 0xf4, 0x1, 0xac, 0x7d, 0xa1, 0x41, 0xa,
+ 0x3e, 0x18, 0x40, 0xeb, 0xe9, 0x22, 0xff, 0x68, 0x8a, 0x1d,
+ 0x12, 0xc6, 0xd0, 0xc1, 0x91, 0xac, 0xb9, 0xa1, 0x5, 0xa,
+ 0x3e, 0x18, 0x49, 0x1f, 0xb9, 0x22, 0xff, 0x78, 0x91, 0xd8,
+ 0x83, 0xf1, 0x74, 0x13, 0x2a, 0xf2, 0x8f, 0x57, 0xd8, 0xf1,
+ 0x60, 0x48, 0x3d, 0x1d, 0xd8, 0x9a, 0x21, 0x9e, 0xa4, 0xe0,
+ 0x83, 0x81, 0x75, 0x16, 0x27, 0xf2, 0x8f, 0x7, 0x88, 0x3d,
+ 0x18, 0x5e, 0x7f, 0x59, 0x22, 0xff, 0xb8, 0x8f, 0xd8, 0x83,
+ 0x20, 0xba, 0xc, 0x12, 0xf9, 0xc7, 0xe5, 0xc4, 0x1e, 0x84,
+ 0xd2, 0x6b, 0x8a, 0xc8, 0x3f, 0x2e, 0x64, 0x77, 0x82, 0x68,
+ 0x3a, 0x3e, 0xe6, 0x9d, 0xaa, 0x73, 0x9e, 0xbd, 0x8, 0x62,
+ 0xea, 0x38, 0xfc, 0x3e, 0x9c, 0xb3, 0x73, 0x8c, 0xd8, 0x83,
+ 0xc8, 0x46, 0x48, 0xe, 0xf9, 0xc7, 0x2e, 0x62, 0xf, 0x18,
+ 0x24, 0x36, 0x34, 0x67, 0xd4, 0xb0, 0x9f, 00, 0x1f, 0x83,
+ 0x84, 0xdf, 0x87, 0x12, 0x90, 0x2d, 0x62, 0xf, 0x58, 0x1a,
+ 0x2d, 0x2d, 0xe4, 0x1f, 0x2b, 0x62, 0xf, 0x48, 0xd, 0x18,
+ 0x15, 0x1a, 0x3b, 0x3e, 0xec, 0x9, 0xc0, 0x96, 0x1, 0xc3,
+ 0xef, 0x43, 0x9, 0x18, 0x99, 0xd8, 0x3, 0xca, 0x46, 0x4e,
+ 0x8, 0x2d, 0x60, 0x40, 0x36, 0x3a, 0x50, 0x63, 0xe4, 0xf0,
+ 0xfb, 0xd0, 0x1a, 0x6, 0x61, 0x43, 0x3, 0xf5, 0xc6, 0xf,
+ 0xbf, 0xf, 0xbd, 0xa0, 0xa3, 0xfa, 0x64, 0xde, 0x24, 0xf6,
+ 0x80, 0x3d, 0x2, 0x45, 0x82, 0xca, 0x60, 0x30, 0x36, 0x28,
+ 0x70, 0x58, 0xa0, 0xf0, 0xfb, 0xd0, 0x62, 0xe, 0xc0, 0x46,
+ 0x4, 0x4e, 0xa, 0x17, 0x7e, 0x1f, 0x5a, 0xcf, 0x1e, 0xe9,
+ 0xe1, 0x4, 0xae, 0x12, 0x34, 0xfc, 0x3e, 0x44, 0x60, 0x2f,
+ 0x6c, 0x29, 0xe0, 0x5a, 0xa1, 0xc3, 0xef, 0x43, 0xc3, 0xda,
+ 0x2c, 0xa5, 0x1e, 0x70, 0x13, 0xe1, 0xf7, 0x87, 0x8, 0x6c,
+ 0x8a, 0xcd, 0x1, 0xdc, 0x4a, 0xf8, 0xfd, 0x45, 0x9b, 0xfb,
+ 0x2e, 0xa5, 0x1e, 0xf0, 0xc, 0xe1, 0x97, 0x21, 0x2, 0x9f,
+ 0x67, 0x9d, 0x3, 0x4f, 0x12, 0x7e, 0x9b, 0x54, 0x21, 0xf,
+ 0xb0, 0x92, 0x81, 0x57, 0x8, 0xbf, 0xef, 0x14, 0x25, 0x97,
+ 0x93, 0x79, 0xc0, 0xbb, 0x84, 0x5f, 0x2d, 0xed, 0xf5, 0x79,
+ 0xd6, 0x21, 0xd0, 0x8, 0xe1, 0xb7, 0x9b, 0x16, 0x7c, 0x2f,
+ 0x6b, 0xc, 0x68, 0x8d, 0xf0, 0x3b, 0x4e, 0x9b, 0x5e, 0x30,
+ 0xaf, 0x9c, 0xc9, 0xfa, 0x1, 0xda, 0x23, 0xfc, 0x2e, 0x20,
+ 0x5, 0x67, 0x56, 0x5, 0xd0, 0x5, 0xe1, 0x77, 0xa5, 0x98,
+ 0xe5, 0x4e, 0xcc, 0x6f, 0xd, 0x74, 0x4d, 0xf8, 0xdd, 0x62,
+ 0xf8, 0x3c, 0x18, 0xfe, 0xb, 0x2, 0x63, 0x13, 0x7e, 0xb7,
+ 0x5b, 0xe6, 0xc4, 0xd4, 0x6d, 0x54, 0x8c, 0xf1, 0x2d, 00,
+ 0x3e, 0x84, 0xdf, 0xd3, 0x7a, 0x49, 0x91, 0x5e, 0x96, 0x13,
+ 0xe0, 00, 0xe1, 0xf7, 0xb2, 0x55, 0xc6, 0x7c, 0x3c, 0xbc,
+ 0x51, 0x5a, 0x58, 0x6, 0x80, 0x27, 0x9, 0xbf, 0x16, 0x65,
+ 0xd3, 0x68, 0xa9, 0x7e, 0xab, 0x7d, 0x9d, 0xd5, 0xae, 0xb9,
+ 0x1, 0x8c, 0x41, 0xf8, 0x75, 0xa9, 0x26, 0xd2, 0x3e, 0x6c,
+ 0x5f, 0x80, 0xd4, 0xff, 0xc2, 0xdb, 0x4d, 0xcb, 00, 00,
+ 00, 0x5, 0x49, 0x44, 0x41, 0x54, 0x1, 0x5b, 0x8a, 0x3b,
+ 0xa9, 0x12, 0xfa, 0x92, 0xf8, 00, 00, 00, 00, 0x49,
+ 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, };
+
+const struct fsdata_file file_404_html[] = {{NULL, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
+
+const struct fsdata_file file_mailinglist_html[] = {{file_404_html, data_mailinglist_html, data_mailinglist_html + 18, sizeof(data_mailinglist_html) - 18}};
+
+const struct fsdata_file file_links_html[] = {{file_mailinglist_html, data_links_html, data_links_html + 12, sizeof(data_links_html) - 12}};
+
+const struct fsdata_file file_licence_html[] = {{file_links_html, data_licence_html, data_licence_html + 14, sizeof(data_licence_html) - 14}};
+
+const struct fsdata_file file_img_sics_gif[] = {{file_licence_html, data_img_sics_gif, data_img_sics_gif + 14, sizeof(data_img_sics_gif) - 14}};
+
+const struct fsdata_file file_index_html[] = {{file_img_sics_gif, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
+
+const struct fsdata_file file_download_html[] = {{file_index_html, data_download_html, data_download_html + 15, sizeof(data_download_html) - 15}};
+
+const struct fsdata_file file_documentation_html[] = {{file_download_html, data_documentation_html, data_documentation_html + 20, sizeof(data_documentation_html) - 20}};
+
+const struct fsdata_file file_os_html[] = {{file_documentation_html, data_os_html, data_os_html + 9, sizeof(data_os_html) - 9}};
+
+const struct fsdata_file file_threads_png[] = {{file_os_html, data_threads_png, data_threads_png + 13, sizeof(data_threads_png) - 13}};
+
+const struct fsdata_file file_os_png[] = {{file_threads_png, data_os_png, data_os_png + 8, sizeof(data_os_png) - 8}};
+
+#define FS_ROOT file_os_png
+
+#define FS_NUMFILES 11
\ No newline at end of file
diff --git a/proj/unixsim/apps/fsdata.h b/proj/unixsim/apps/fsdata.h
new file mode 100644
index 0000000..4ee3db9
--- /dev/null
+++ b/proj/unixsim/apps/fsdata.h
@@ -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__ */
diff --git a/proj/unixsim/apps/httpd.c b/proj/unixsim/apps/httpd.c
new file mode 100644
index 0000000..4b391ba
--- /dev/null
+++ b/proj/unixsim/apps/httpd.c
@@ -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);
+}
+/*-----------------------------------------------------------------------------------*/
+
diff --git a/proj/unixsim/apps/httpd.h b/proj/unixsim/apps/httpd.h
new file mode 100644
index 0000000..323a3a0
--- /dev/null
+++ b/proj/unixsim/apps/httpd.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __HTTPD_H__
+#define __HTTPD_H__
+
+void httpd_init(void);
+
+#endif /* __HTTPD_H__ */
diff --git a/proj/unixsim/apps/makefsdata b/proj/unixsim/apps/makefsdata
new file mode 100644
index 0000000..90dee2f
--- /dev/null
+++ b/proj/unixsim/apps/makefsdata
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+open(OUTPUT, "> fsdata.c");
+
+chdir("fs");
+open(FILES, "find . -type f |");
+
+while($file = <FILES>) {
+
+ # Do not include files in CVS directories nor backup files.
+ if($file =~ /(CVS|~)/) {
+ next;
+ }
+
+ chop($file);
+
+ open(HEADER, "> /tmp/header") || die $!;
+ if($file =~ /404/) {
+ print(HEADER "HTTP/1.0 404 File not found\r\n");
+ } else {
+ print(HEADER "HTTP/1.0 200 OK\r\n");
+ }
+ print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n");
+ if($file =~ /\.html$/) {
+ print(HEADER "Content-type: text/html\r\n");
+ } elsif($file =~ /\.gif$/) {
+ print(HEADER "Content-type: image/gif\r\n");
+ } elsif($file =~ /\.png$/) {
+ print(HEADER "Content-type: image/png\r\n");
+ } elsif($file =~ /\.jpg$/) {
+ print(HEADER "Content-type: image/jpeg\r\n");
+ } elsif($file =~ /\.class$/) {
+ print(HEADER "Content-type: application/octet-stream\r\n");
+ } elsif($file =~ /\.ram$/) {
+ print(HEADER "Content-type: audio/x-pn-realaudio\r\n");
+ } else {
+ print(HEADER "Content-type: text/plain\r\n");
+ }
+ print(HEADER "\r\n");
+ close(HEADER);
+
+ unless($file =~ /\.plain$/ || $file =~ /cgi/) {
+ system("cat /tmp/header $file > /tmp/file");
+ } else {
+ system("cp $file /tmp/file");
+ }
+
+ open(FILE, "/tmp/file");
+ unlink("/tmp/file");
+ unlink("/tmp/header");
+
+ $file =~ s/\.//;
+ $fvar = $file;
+ $fvar =~ s-/-_-g;
+ $fvar =~ s-\.-_-g;
+ 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)));
+ }
+ printf(OUTPUT "0,\n");
+
+
+ $i = 0;
+ while(read(FILE, $data, 1)) {
+ if($i == 0) {
+ print(OUTPUT "\t");
+ }
+ printf(OUTPUT "%#02x, ", unpack("C", $data));
+ $i++;
+ if($i == 10) {
+ print(OUTPUT "\n");
+ $i = 0;
+ }
+ }
+ print(OUTPUT "};\n\n");
+ close(FILE);
+ push(@fvars, $fvar);
+ push(@files, $file);
+}
+
+for($i = 0; $i < @fvars; $i++) {
+ $file = $files[$i];
+ $fvar = $fvars[$i];
+
+ if($i == 0) {
+ $prevfile = "NULL";
+ } else {
+ $prevfile = "file" . $fvars[$i - 1];
+ }
+ print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
+ print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
+ print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
+}
+
+print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
+print(OUTPUT "#define FS_NUMFILES $i");
diff --git a/proj/unixsim/apps/shell.c b/proj/unixsim/apps/shell.c
new file mode 100644
index 0000000..e6f1a31
--- /dev/null
+++ b/proj/unixsim/apps/shell.c
@@ -0,0 +1,1056 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+
+#include "lwip/mem.h"
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/api.h"
+#include "lwip/stats.h"
+
+static unsigned char buffer[1024];
+
+struct command {
+ struct netconn *conn;
+ s8_t (* exec)(struct command *);
+ u8_t nargs;
+ char *args[10];
+};
+
+#include <stdio.h>
+#include <errno.h>
+
+#define ESUCCESS 0
+#define ESYNTAX -1
+#define ETOOFEW -2
+#define ETOOMANY -3
+#define ECLOSED -4
+
+#define NCONNS 10
+static struct netconn *conns[NCONNS];
+
+static char help_msg[] = "Avaliable commands:\n\
+open [IP address] [TCP port]: opens a TCP connection to the specified address.\n\
+lstn [TCP port]: sets up a server on the specified port.\n\
+acpt [connection #]: waits for an incoming connection request.\n\
+send [connection #] [message]: sends a message on a TCP connection.\n\
+udpc [local UDP port] [IP address] [remote port]: opens a UDP \"connection\".\n\
+udpl [local UDP port] [IP address] [remote port]: opens a UDP-Lite \"connection\".\n\
+udpn [local UDP port] [IP address] [remote port]: opens a UDP \"connection\" without checksums.\n\
+udpb [local port] [remote port]: opens a UDP broadcast \"connection\".\n\
+usnd [connection #] [message]: sends a message on a UDP connection.\n\
+recv [connection #]: recieves data on a TCP or UDP connection.\n\
+clos [connection #]: closes a TCP or UDP connection.\n\
+stat: prints out lwIP statistics.\n\
+quit: quits.\n";
+
+static char *stat_msgs[] = {
+ "Link level * transmitted ",
+ " retransmitted ",
+ " * received ",
+ " forwarded ",
+ " * dropped ",
+ " * checksum errors ",
+ " * length errors ",
+ " * memory errors ",
+ " routing errors ",
+ " protocol errors ",
+ " option errors ",
+ " * misc errors ",
+ " cache hits ",
+ "IP * transmitted ",
+ " retransmitted ",
+ " * received ",
+ " * forwarded ",
+ " * dropped ",
+ " * checksum errors ",
+ " * length errors ",
+ " * memory errors ",
+ " * routing errors ",
+ " * protocol errors ",
+ " * option errors ",
+ " * misc errors ",
+ " cache hits ",
+ "ICMP * transmitted ",
+ " retransmitted ",
+ " * received ",
+ " forwarded ",
+ " * dropped ",
+ " * checksum errors ",
+ " length errors ",
+ " * memory errors ",
+ " routing errors ",
+ " * protocol errors ",
+ " option errors ",
+ " * misc errors ",
+ " cache hits ",
+ "UDP * transmitted ",
+ " retransmitted ",
+ " * received ",
+ " forwarded ",
+ " * dropped ",
+ " * checksum errors ",
+ " * length errors ",
+ " * memory errors ",
+ " * routing errors ",
+ " * protocol errors ",
+ " option errors ",
+ " * misc errors ",
+ " cache hits ",
+ "TCP * transmitted ",
+ " * retransmitted ",
+ " * received ",
+ " forwarded ",
+ " * dropped ",
+ " * checksum errors ",
+ " * length errors ",
+ " * memory errors ",
+ " * routing errors ",
+ " * protocol errors ",
+ " * option errors ",
+ " * misc errors ",
+ " * cache hits ",
+ "Pbufs * avaiable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " reclaimed ",
+ " pbuf_alloc() locked ",
+ " pbuf_refresh() locked ",
+ "Memory * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "Memp PBUF * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "UDP PCB * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "TCP PCB * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "TCP LISTEN * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "TCP SEG * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "Netbufs * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "Netconns * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "API msgs * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "TCPIP msgs * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "Timeouts * avaliable ",
+ " * used ",
+ " * high water mark ",
+ " * errors ",
+ " * reclaimed ",
+ "Semaphores * used ",
+ " * high water mark ",
+ " * errors ",
+ "Mailboxes * used ",
+ " * high water mark ",
+ " * errors "
+};
+/*-----------------------------------------------------------------------------------*/
+static void
+sendstr(const char *str, struct netconn *conn)
+{
+ netconn_write(conn, (void *)str, strlen(str), NETCONN_NOCOPY);
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_open(struct command *com)
+{
+ struct ip_addr ipaddr;
+ u16_t port;
+ int i;
+ err_t err;
+
+ if(inet_aton(com->args[0], &ipaddr) == -1) {
+ sendstr(strerror(errno), com->conn);
+ return ESYNTAX;
+ }
+ port = strtol(com->args[1], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Opening connection to ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr(":", com->conn);
+ netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_TCP);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+ err = netconn_connect(conns[i], &ipaddr, port);
+ if(err != ERR_OK) {
+ fprintf(stderr, "error %s\n", lwip_strerr(err));
+ sendstr("Could not connect to remote host: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ return ESUCCESS;
+ }
+
+ sendstr("Opened connection, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_lstn(struct command *com)
+{
+ u16_t port;
+ int i;
+ err_t err;
+
+ port = strtol(com->args[0], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Opening a listening connection on port ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_TCP);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_bind(conns[i], IP_ADDR_ANY, port);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not bind: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_listen(conns[i]);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not listen: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Opened connection, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_clos(struct command *com)
+{
+ int i;
+ err_t err;
+
+ i = strtol(com->args[0], NULL, 10);
+
+ if(i > NCONNS) {
+ sendstr("Connection identifier too high.\n", com->conn);
+ return ESUCCESS;
+ }
+ if(conns[i] == NULL) {
+ sendstr("Connection identifier not in use.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_close(conns[i]);
+ if(err != ERR_OK) {
+ sendstr("Could not close connection: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Connection closed.\n", com->conn);
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_acpt(struct command *com)
+{
+ int i, j;
+
+ /* Find the first unused connection in conns. */
+ for(j = 0; j < NCONNS && conns[j] != NULL; j++);
+
+ if(j == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ i = strtol(com->args[0], NULL, 10);
+
+ if(i > NCONNS) {
+ sendstr("Connection identifier too high.\n", com->conn);
+ return ESUCCESS;
+ }
+ if(conns[i] == NULL) {
+ sendstr("Connection identifier not in use.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ conns[j] = netconn_accept(conns[i]);
+
+ if(conns[j] == NULL) {
+ sendstr("Could not accept connection: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(netconn_err(conns[i])), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Accepted connection, connection identifier for new connection is ", com->conn);
+ sprintf(buffer, "%d\n", j);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_stat(struct command *com)
+{
+ int i;
+ char buf[100];
+ u16_t len;
+
+ for(i = 0; i < sizeof(struct stats_) / 2; i++) {
+ len = sprintf(buf, "%d", ((u16_t *)&stats)[i]);
+ sendstr(stat_msgs[i], com->conn);
+ netconn_write(com->conn, buf, len, NETCONN_COPY);
+ sendstr("\n", com->conn);
+ }
+
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_send(struct command *com)
+{
+ int i;
+ err_t err;
+ int len;
+
+ i = strtol(com->args[0], NULL, 10);
+
+ if(i > NCONNS) {
+ sendstr("Connection identifier too high.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ if(conns[i] == NULL) {
+ sendstr("Connection identifier not in use.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ len = strlen(com->args[1]);
+ com->args[1][len] = '\r';
+ com->args[1][len + 1] = '\n';
+ com->args[1][len + 2] = 0;
+
+ err = netconn_write(conns[i], com->args[1], len + 3, NETCONN_COPY);
+ if(err != ERR_OK) {
+ sendstr("Could not send data: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Data enqueued for sending.\n", com->conn);
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_recv(struct command *com)
+{
+ int i;
+ err_t err;
+ struct netbuf *buf;
+ u16_t len;
+
+ i = strtol(com->args[0], NULL, 10);
+
+ if(i > NCONNS) {
+ sendstr("Connection identifier too high.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ if(conns[i] == NULL) {
+ sendstr("Connection identifier not in use.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ buf = netconn_recv(conns[i]);
+ if(buf != NULL) {
+
+ netbuf_copy(buf, buffer, 1024);
+ len = netbuf_len(buf);
+ sendstr("Reading from connection:\n", com->conn);
+ netconn_write(com->conn, buffer, len, NETCONN_COPY);
+ netbuf_delete(buf);
+ } else {
+ sendstr("EOF.\n", com->conn);
+ }
+ err = netconn_err(conns[i]);
+ if(err != ERR_OK) {
+ sendstr("Could not receive data: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_udpc(struct command *com)
+{
+ struct ip_addr ipaddr;
+ u16_t lport, rport;
+ int i;
+ err_t err;
+
+ lport = strtol(com->args[0], NULL, 10);
+ if(inet_aton(com->args[1], &ipaddr) == -1) {
+ sendstr(strerror(errno), com->conn);
+ return ESYNTAX;
+ }
+ rport = strtol(com->args[2], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Setting up UDP connection from port ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr(" to ", com->conn);
+ netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
+ sendstr(":", com->conn);
+ netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_UDP);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_connect(conns[i], &ipaddr, rport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not connect to remote host: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not bind: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Connection set up, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_udpl(struct command *com)
+{
+ struct ip_addr ipaddr;
+ u16_t lport, rport;
+ int i;
+ err_t err;
+
+ lport = strtol(com->args[0], NULL, 10);
+ if(inet_aton(com->args[1], &ipaddr) == -1) {
+ sendstr(strerror(errno), com->conn);
+ return ESYNTAX;
+ }
+ rport = strtol(com->args[2], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Setting up UDP-Lite connection from port ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr(" to ", com->conn);
+ netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
+ sendstr(":", com->conn);
+ netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_UDPLITE);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_connect(conns[i], &ipaddr, rport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not connect to remote host: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not bind: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Connection set up, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_udpn(struct command *com)
+{
+ struct ip_addr ipaddr;
+ u16_t lport, rport;
+ int i;
+ err_t err;
+
+ lport = strtol(com->args[0], NULL, 10);
+ if(inet_aton(com->args[1], &ipaddr) == -1) {
+ sendstr(strerror(errno), com->conn);
+ return ESYNTAX;
+ }
+ rport = strtol(com->args[2], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Setting up UDP connection without checksums from port ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr(" to ", com->conn);
+ netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
+ sendstr(":", com->conn);
+ netconn_write(com->conn, com->args[2], strlen(com->args[2]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_UDPNOCHKSUM);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_connect(conns[i], &ipaddr, rport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not connect to remote host: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_bind(conns[i], IP_ADDR_ANY, lport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not bind: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Connection set up, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_udpb(struct command *com)
+{
+ struct ip_addr ipaddr;
+ u16_t lport, rport;
+ int i;
+ err_t err;
+ struct ip_addr bcaddr;
+
+ lport = strtol(com->args[0], NULL, 10);
+ if(inet_aton(com->args[1], &ipaddr) == -1) {
+ sendstr(strerror(errno), com->conn);
+ return ESYNTAX;
+ }
+ rport = strtol(com->args[2], NULL, 10);
+
+ /* Find the first unused connection in conns. */
+ for(i = 0; i < NCONNS && conns[i] != NULL; i++);
+
+ if(i == NCONNS) {
+ sendstr("No more connections avaliable, sorry.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Setting up UDP broadcast connection from port ", com->conn);
+ netconn_write(com->conn, com->args[0], strlen(com->args[0]), NETCONN_COPY);
+ sendstr(" to ", com->conn);
+ netconn_write(com->conn, com->args[1], strlen(com->args[1]), NETCONN_COPY);
+ sendstr("\n", com->conn);
+
+ conns[i] = netconn_new(NETCONN_UDP);
+ if(conns[i] == NULL) {
+ sendstr("Could not create connection identifier (out of memory).\n", com->conn);
+ return ESUCCESS;
+ }
+
+ err = netconn_connect(conns[i], &ipaddr, rport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not connect to remote host: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ IP4_ADDR(&bcaddr, 255,255,255,255);
+ err = netconn_bind(conns[i], &bcaddr, lport);
+ if(err != ERR_OK) {
+ netconn_delete(conns[i]);
+ conns[i] = NULL;
+ sendstr("Could not bind: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Connection set up, connection identifier is ", com->conn);
+ sprintf(buffer, "%d\n", i);
+ netconn_write(com->conn, buffer, strlen(buffer), NETCONN_COPY);
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_usnd(struct command *com)
+{
+ int i;
+ err_t err;
+ struct netbuf *buf;
+ char *mem;
+
+ i = strtol(com->args[0], NULL, 10);
+
+ if(i > NCONNS) {
+ sendstr("Connection identifier too high.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ if(conns[i] == NULL) {
+ sendstr("Connection identifier not in use.\n", com->conn);
+ return ESUCCESS;
+ }
+
+ buf = netbuf_new();
+ mem = netbuf_alloc(buf, strlen(com->args[1]) + 1);
+ if(mem == NULL) {
+ sendstr("Could not allocate memory for sending.\n", com->conn);
+ return ESUCCESS;
+ }
+ strncpy(mem, com->args[1], strlen(com->args[1]) + 1);
+ err = netconn_send(conns[i], buf);
+ netbuf_delete(buf);
+ if(err != ERR_OK) {
+ sendstr("Could not send data: ", com->conn);
+#ifdef LWIP_DEBUG
+ sendstr(lwip_strerr(err), com->conn);
+#else
+ sendstr("(debugging must be turned on for error message to appear)", com->conn);
+#endif /* LWIP_DEBUG */
+ sendstr("\n", com->conn);
+ return ESUCCESS;
+ }
+
+ sendstr("Data sent.\n", com->conn);
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+com_help(struct command *com)
+{
+ sendstr(help_msg, com->conn);
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static s8_t
+parse_command(struct command *com, u32_t len)
+{
+ u16_t i;
+ u16_t bufp;
+
+ if(strncmp(buffer, "open", 4) == 0) {
+ com->exec = com_open;
+ com->nargs = 2;
+ } else if(strncmp(buffer, "lstn", 4) == 0) {
+ com->exec = com_lstn;
+ com->nargs = 1;
+ } else if(strncmp(buffer, "acpt", 4) == 0) {
+ com->exec = com_acpt;
+ com->nargs = 1;
+ } else if(strncmp(buffer, "clos", 4) == 0) {
+ com->exec = com_clos;
+ com->nargs = 1;
+ } else if(strncmp(buffer, "stat", 4) == 0) {
+ com->exec = com_stat;
+ com->nargs = 0;
+ } else if(strncmp(buffer, "send", 4) == 0) {
+ com->exec = com_send;
+ com->nargs = 2;
+ } else if(strncmp(buffer, "recv", 4) == 0) {
+ com->exec = com_recv;
+ com->nargs = 1;
+ } else if(strncmp(buffer, "udpc", 4) == 0) {
+ com->exec = com_udpc;
+ com->nargs = 3;
+ } else if(strncmp(buffer, "udpb", 4) == 0) {
+ com->exec = com_udpb;
+ com->nargs = 2;
+ } else if(strncmp(buffer, "udpl", 4) == 0) {
+ com->exec = com_udpl;
+ com->nargs = 3;
+ } else if(strncmp(buffer, "udpn", 4) == 0) {
+ com->exec = com_udpn;
+ com->nargs = 3;
+ } else if(strncmp(buffer, "usnd", 4) == 0) {
+ com->exec = com_usnd;
+ com->nargs = 2;
+ } else if(strncmp(buffer, "help", 4) == 0) {
+ com->exec = com_help;
+ com->nargs = 0;
+ } else if(strncmp(buffer, "quit", 4) == 0) {
+ printf("quit\n");
+ return ECLOSED;
+ } else {
+ return ESYNTAX;
+ }
+
+ if(com->nargs == 0) {
+ return ESUCCESS;
+ }
+ bufp = 0;
+ for(; bufp < len && buffer[bufp] != ' '; bufp++);
+ for(i = 0; i < 10; i++) {
+ for(; bufp < len && buffer[bufp] == ' '; bufp++);
+ if(buffer[bufp] == '\r' ||
+ buffer[bufp] == '\n') {
+ buffer[bufp] = 0;
+ if(i < com->nargs - 1) {
+ return ETOOFEW;
+ }
+ if(i > com->nargs - 1) {
+ return ETOOMANY;
+ }
+ break;
+ }
+ if(bufp > len) {
+ return ETOOFEW;
+ }
+ com->args[i] = &buffer[bufp];
+ for(; bufp < len && buffer[bufp] != ' ' && buffer[bufp] != '\r' &&
+ buffer[bufp] != '\n'; bufp++) {
+ if(buffer[bufp] == '\\') {
+ buffer[bufp] = ' ';
+ }
+ }
+ if(bufp > len) {
+ return ESYNTAX;
+ }
+ buffer[bufp] = 0;
+ bufp++;
+ if(i == com->nargs - 1) {
+ break;
+ }
+
+ }
+
+ return ESUCCESS;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+error(s8_t err, struct netconn *conn)
+{
+ switch(err) {
+ case ESYNTAX:
+ sendstr("## Syntax error\n", conn);
+ break;
+ case ETOOFEW:
+ sendstr("## Too few arguments to command given\n", conn);
+ break;
+ case ETOOMANY:
+ sendstr("## Too many arguments to command given\n", conn);
+ break;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+prompt(struct netconn *conn)
+{
+ sendstr("> ", conn);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+shell_main(struct netconn *conn)
+{
+ struct netbuf *buf;
+ u32_t len;
+ struct command com;
+ s8_t err;
+ int i;
+
+ do {
+ buf = netconn_recv(conn);
+ if(buf != NULL) {
+ netbuf_copy(buf, buffer, 1024);
+ len = netbuf_len(buf);
+ netbuf_delete(buf);
+ if(len >= 4) {
+ if(buffer[0] != 0xff &&
+ buffer[1] != 0xfe) {
+ err = parse_command(&com, len);
+ if(err == ESUCCESS) {
+ com.conn = conn;
+ err = com.exec(&com);
+ }
+ if(err != ESUCCESS) {
+ error(err, conn);
+ }
+ if(err == ECLOSED) {
+ printf("Closed\n");
+ error(err, conn);
+ goto close;
+ }
+ } else {
+ sendstr("\n\n"
+ "lwIP simple interactive shell.\n"
+ "(c) Copyright 2001, Swedish Institute of Computer Science.\n"
+ "Written by Adam Dunkels.\n"
+ "For help, try the \"help\" command.\n", conn);
+ }
+ }
+ }
+ if(buf != NULL) {
+ prompt(conn);
+ }
+ } while(buf != NULL);
+ printf("buf == NULL err %s\n", lwip_strerr(conn->err));
+ close:
+ netconn_close(conn);
+
+ for(i = 0; i < NCONNS; i++) {
+ if(conns[i] != NULL) {
+ netconn_delete(conns[i]);
+ }
+ conns[i] = NULL;
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+shell_thread(void *arg)
+{
+ struct netconn *conn, *newconn;
+
+ conn = netconn_new(NETCONN_TCP);
+ netconn_bind(conn, NULL, 23);
+ netconn_listen(conn);
+
+ while(1) {
+ newconn = netconn_accept(conn);
+ shell_main(newconn);
+ netconn_delete(newconn);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+shell_init(void)
+{
+ sys_thread_new(shell_thread, NULL);
+}
+
+
+
+
diff --git a/proj/unixsim/apps/shell.h b/proj/unixsim/apps/shell.h
new file mode 100644
index 0000000..34e648b
--- /dev/null
+++ b/proj/unixsim/apps/shell.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __SHELL_H__
+#define __SHELL_H__
+
+void shell_init(void);
+
+#endif /* __SHELL_H__ */
diff --git a/proj/unixsim/apps/tcpecho.c b/proj/unixsim/apps/tcpecho.c
new file mode 100644
index 0000000..eacf95e
--- /dev/null
+++ b/proj/unixsim/apps/tcpecho.c
@@ -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);
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
diff --git a/proj/unixsim/apps/tcpecho.h b/proj/unixsim/apps/tcpecho.h
new file mode 100644
index 0000000..8331852
--- /dev/null
+++ b/proj/unixsim/apps/tcpecho.h
@@ -0,0 +1,38 @@
+/*
+ * 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 __TCPECHO_H__
+#define __TCPECHO_H__
+
+void tcpecho_init(void);
+
+#endif /* __TCPECHO_H__ */
diff --git a/proj/unixsim/apps/udpecho.c b/proj/unixsim/apps/udpecho.c
new file mode 100644
index 0000000..50239a0
--- /dev/null
+++ b/proj/unixsim/apps/udpecho.c
@@ -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);
+}
diff --git a/proj/unixsim/apps/udpecho.h b/proj/unixsim/apps/udpecho.h
new file mode 100644
index 0000000..e955f98
--- /dev/null
+++ b/proj/unixsim/apps/udpecho.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __UDPECHO_H__
+#define __UDPECHO_H__
+
+void udpecho_init(void);
+
+#endif /* __UDPECHO_H__ */
diff --git a/proj/unixsim/lwipopts.h b/proj/unixsim/lwipopts.h
new file mode 100644
index 0000000..fcc1944
--- /dev/null
+++ b/proj/unixsim/lwipopts.h
@@ -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__ */
diff --git a/proj/unixsim/simhost.c b/proj/unixsim/simhost.c
new file mode 100644
index 0000000..0859003
--- /dev/null
+++ b/proj/unixsim/simhost.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
diff --git a/proj/unixsim/simnode.c b/proj/unixsim/simnode.c
new file mode 100644
index 0000000..f20fa18
--- /dev/null
+++ b/proj/unixsim/simnode.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
diff --git a/proj/unixsim/simrouter.c b/proj/unixsim/simrouter.c
new file mode 100644
index 0000000..bd43aa4
--- /dev/null
+++ b/proj/unixsim/simrouter.c
@@ -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;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
diff --git a/src/FILES b/src/FILES
new file mode 100644
index 0000000..c66ca36
--- /dev/null
+++ b/src/FILES
@@ -0,0 +1,13 @@
+api/ - The code for the 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.
+
+For more information on the various subdirectories, check the FILES
+file in each directory.
diff --git a/src/api/api_lib.c b/src/api/api_lib.c
new file mode 100644
index 0000000..da2def3
--- /dev/null
+++ b/src/api/api_lib.c
@@ -0,0 +1,639 @@
+/*
+ * 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>
+ *
+ */
+
+/* This is the part of the API that is linked with
+ the application */
+
+#include "lwip/debug.h"
+#include "lwip/api.h"
+#include "lwip/api_msg.h"
+#include "lwip/memp.h"
+
+#include "lwip/debug.h"
+
+/*-----------------------------------------------------------------------------------*/
+struct
+netbuf *netbuf_new(void)
+{
+ struct netbuf *buf;
+
+ buf = memp_mallocp(MEMP_NETBUF);
+ if(buf != NULL) {
+ buf->p = NULL;
+ buf->ptr = NULL;
+ return buf;
+ } else {
+ return NULL;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_delete(struct netbuf *buf)
+{
+ if(buf != NULL) {
+ if(buf->p != NULL) {
+ pbuf_free(buf->p);
+ buf->p = buf->ptr = NULL;
+ }
+ memp_freep(MEMP_NETBUF, buf);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+netbuf_alloc(struct netbuf *buf, u16_t size)
+{
+ /* 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;
+ }
+ buf->ptr = buf->p;
+ return buf->p->payload;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_free(struct netbuf *buf)
+{
+ if(buf->p != NULL) {
+ pbuf_free(buf->p);
+ }
+ buf->p = buf->ptr = NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
+{
+ if(buf->p != NULL) {
+ pbuf_free(buf->p);
+ }
+ buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_ROM);
+ buf->p->payload = dataptr;
+ buf->p->len = buf->p->tot_len = size;
+ buf->ptr = buf->p;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_chain(struct netbuf *head, struct netbuf *tail)
+{
+ pbuf_chain(head->p, tail->p);
+ head->ptr = head->p;
+ memp_freep(MEMP_NETBUF, tail);
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+netbuf_len(struct netbuf *buf)
+{
+ return buf->p->tot_len;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
+{
+ if(buf->ptr == NULL) {
+ return ERR_BUF;
+ }
+ *dataptr = buf->ptr->payload;
+ *len = buf->ptr->len;
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+s8_t
+netbuf_next(struct netbuf *buf)
+{
+ if(buf->ptr->next == NULL) {
+ return -1;
+ }
+ buf->ptr = buf->ptr->next;
+ if(buf->ptr->next == NULL) {
+ return 1;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_first(struct netbuf *buf)
+{
+ buf->ptr = buf->p;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
+{
+ struct pbuf *p;
+ u16_t i, left;
+
+ left = 0;
+
+ if(buf == NULL) {
+ return;
+ }
+
+ /* This implementation is bad. It should use bcopy
+ instead. */
+ for(p = buf->p; left < len && p != NULL; p = p->next) {
+ if(offset != 0 && offset >= p->len) {
+ offset -= p->len;
+ } else {
+ for(i = offset; i < p->len; ++i) {
+ ((char *)dataptr)[left] = ((char *)p->payload)[i];
+ if(++left >= len) {
+ return;
+ }
+ }
+ offset = 0;
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
+{
+ netbuf_copy_partial(buf, dataptr, len, 0);
+}
+/*-----------------------------------------------------------------------------------*/
+struct ip_addr *
+netbuf_fromaddr(struct netbuf *buf)
+{
+ return buf->fromaddr;
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+netbuf_fromport(struct netbuf *buf)
+{
+ return buf->fromport;
+}
+/*-----------------------------------------------------------------------------------*/
+struct
+netconn *netconn_new(enum netconn_type t)
+{
+ struct netconn *conn;
+
+ conn = memp_mallocp(MEMP_NETCONN);
+ if(conn == NULL) {
+ return NULL;
+ }
+ conn->type = t;
+ conn->pcb.tcp = NULL;
+
+ if((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
+ memp_freep(MEMP_NETCONN, conn);
+ return NULL;
+ }
+ conn->recvmbox = SYS_MBOX_NULL;
+ conn->acceptmbox = SYS_MBOX_NULL;
+ conn->sem = SYS_SEM_NULL;
+ conn->state = NETCONN_NONE;
+ return conn;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_delete(struct netconn *conn)
+{
+ struct api_msg *msg;
+ void *mem;
+
+ if(conn == NULL) {
+ return ERR_OK;
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return ERR_MEM;
+ }
+
+ msg->type = API_MSG_DELCONN;
+ msg->msg.conn = conn;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+
+ /* Drain the recvmbox. */
+ if(conn->recvmbox != SYS_MBOX_NULL) {
+ while(sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != 0) {
+ if(conn->type == NETCONN_TCP) {
+ pbuf_free((struct pbuf *)mem);
+ } else {
+ netbuf_delete((struct netbuf *)mem);
+ }
+ }
+ sys_mbox_free(conn->recvmbox);
+ conn->recvmbox = SYS_MBOX_NULL;
+ }
+
+
+ /* Drain the acceptmbox. */
+ if(conn->acceptmbox != SYS_MBOX_NULL) {
+ while(sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != 0) {
+ netconn_delete((struct netconn *)mem);
+ }
+
+ sys_mbox_free(conn->acceptmbox);
+ conn->acceptmbox = SYS_MBOX_NULL;
+ }
+
+ sys_mbox_free(conn->mbox);
+ conn->mbox = SYS_MBOX_NULL;
+ if(conn->sem != SYS_SEM_NULL) {
+ sys_sem_free(conn->sem);
+ }
+ /* conn->sem = SYS_SEM_NULL;*/
+ memp_free(MEMP_NETCONN, conn);
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+enum netconn_type
+netconn_type(struct netconn *conn)
+{
+ return conn->type;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_peer(struct netconn *conn, struct ip_addr **addr,
+ u16_t *port)
+{
+ switch(conn->type) {
+ case NETCONN_UDPLITE:
+ case NETCONN_UDPNOCHKSUM:
+ case NETCONN_UDP:
+ *addr = &(conn->pcb.udp->remote_ip);
+ *port = conn->pcb.udp->remote_port;
+ break;
+ case NETCONN_TCP:
+ *addr = &(conn->pcb.tcp->remote_ip);
+ *port = conn->pcb.tcp->remote_port;
+ break;
+ }
+ return (conn->err = ERR_OK);
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_addr(struct netconn *conn, struct ip_addr **addr,
+ u16_t *port)
+{
+ switch(conn->type) {
+ case NETCONN_UDPLITE:
+ case NETCONN_UDPNOCHKSUM:
+ case NETCONN_UDP:
+ *addr = &(conn->pcb.udp->local_ip);
+ *port = conn->pcb.udp->local_port;
+ break;
+ case NETCONN_TCP:
+ *addr = &(conn->pcb.tcp->local_ip);
+ *port = conn->pcb.tcp->local_port;
+ break;
+ }
+ return (conn->err = ERR_OK);
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_bind(struct netconn *conn, struct ip_addr *addr,
+ u16_t port)
+{
+ struct api_msg *msg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+ if(conn->type != NETCONN_TCP &&
+ conn->recvmbox == SYS_MBOX_NULL) {
+ if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
+ return ERR_MEM;
+ }
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return (conn->err = ERR_MEM);
+ }
+ msg->type = API_MSG_BIND;
+ msg->msg.conn = conn;
+ msg->msg.msg.bc.ipaddr = addr;
+ msg->msg.msg.bc.port = port;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_connect(struct netconn *conn, struct ip_addr *addr,
+ u16_t port)
+{
+ struct api_msg *msg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+
+ if(conn->recvmbox == SYS_MBOX_NULL) {
+ if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
+ return ERR_MEM;
+ }
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return ERR_MEM;
+ }
+ msg->type = API_MSG_CONNECT;
+ msg->msg.conn = conn;
+ msg->msg.msg.bc.ipaddr = addr;
+ msg->msg.msg.bc.port = port;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_listen(struct netconn *conn)
+{
+ struct api_msg *msg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+ if(conn->acceptmbox == SYS_MBOX_NULL) {
+ conn->acceptmbox = sys_mbox_new();
+ if(conn->acceptmbox == SYS_MBOX_NULL) {
+ return ERR_MEM;
+ }
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return (conn->err = ERR_MEM);
+ }
+ msg->type = API_MSG_LISTEN;
+ msg->msg.conn = conn;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+struct netconn *
+netconn_accept(struct netconn *conn)
+{
+ struct netconn *newconn;
+
+ if(conn == NULL) {
+ return NULL;
+ }
+
+ sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
+
+ return newconn;
+}
+/*-----------------------------------------------------------------------------------*/
+struct netbuf *
+netconn_recv(struct netconn *conn)
+{
+ struct api_msg *msg;
+ struct netbuf *buf;
+ struct pbuf *p;
+
+ if(conn == NULL) {
+ return NULL;
+ }
+
+ if(conn->recvmbox == SYS_MBOX_NULL) {
+ conn->err = ERR_CONN;
+ return NULL;
+ }
+
+ if(conn->err != ERR_OK) {
+ return NULL;
+ }
+
+ if(conn->type == NETCONN_TCP) {
+ if(conn->pcb.tcp->state == LISTEN) {
+ conn->err = ERR_CONN;
+ return NULL;
+ }
+
+
+ buf = memp_mallocp(MEMP_NETBUF);
+
+ if(buf == NULL) {
+ conn->err = ERR_MEM;
+ return NULL;
+ }
+
+ sys_mbox_fetch(conn->recvmbox, (void **)&p);
+
+ /* If we are closed, we indicate that we no longer wish to recieve
+ data by setting conn->recvmbox to SYS_MBOX_NULL. */
+ if(p == NULL) {
+ memp_freep(MEMP_NETBUF, buf);
+ sys_mbox_free(conn->recvmbox);
+ conn->recvmbox = SYS_MBOX_NULL;
+ return NULL;
+ }
+
+ buf->p = p;
+ buf->ptr = p;
+ buf->fromport = 0;
+ buf->fromaddr = NULL;
+
+ /* Let the stack know that we have taken the data. */
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ conn->err = ERR_MEM;
+ return buf;
+ }
+ msg->type = API_MSG_RECV;
+ msg->msg.conn = conn;
+ if(buf != NULL) {
+ msg->msg.msg.len = buf->p->tot_len;
+ } else {
+ msg->msg.msg.len = 1;
+ }
+ api_msg_post(msg);
+
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+ } else {
+ sys_mbox_fetch(conn->recvmbox, (void **)&buf);
+ }
+
+
+
+
+ DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", buf, conn->err));
+
+
+ return buf;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_send(struct netconn *conn, struct netbuf *buf)
+{
+ struct api_msg *msg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+ if(conn->err != ERR_OK) {
+ return conn->err;
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return (conn->err = ERR_MEM);
+ }
+
+ DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
+ msg->type = API_MSG_SEND;
+ msg->msg.conn = conn;
+ msg->msg.msg.p = buf->p;
+ api_msg_post(msg);
+
+ sys_mbox_fetch(conn->mbox, NULL);
+ memp_freep(MEMP_API_MSG, msg);
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
+{
+ struct api_msg *msg;
+ u16_t len;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+ if(conn->err != ERR_OK) {
+ return conn->err;
+ }
+
+ if(conn->sem == SYS_SEM_NULL) {
+ conn->sem = sys_sem_new(0);
+ if(conn->sem == SYS_SEM_NULL) {
+ return ERR_MEM;
+ }
+ }
+
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return (conn->err = ERR_MEM);
+ }
+ msg->type = API_MSG_WRITE;
+ msg->msg.conn = conn;
+
+
+ conn->state = NETCONN_WRITE;
+ while(conn->err == ERR_OK && size > 0) {
+ msg->msg.msg.w.dataptr = dataptr;
+ msg->msg.msg.w.copy = copy;
+
+ if(conn->type == NETCONN_TCP) {
+ if(tcp_sndbuf(conn->pcb.tcp) == 0) {
+ sys_sem_wait(conn->sem);
+ if(conn->err != ERR_OK) {
+ goto ret;
+ }
+ }
+ if(size > tcp_sndbuf(conn->pcb.tcp)) {
+ /* We cannot send more than one send buffer's worth of data at a
+ time. */
+ len = tcp_sndbuf(conn->pcb.tcp);
+ } else {
+ len = size;
+ }
+ } else {
+ len = size;
+ }
+
+ DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
+ msg->msg.msg.w.len = len;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ if(conn->err == ERR_OK) {
+ dataptr = (void *)((char *)dataptr + len);
+ size -= len;
+ } else if(conn->err == ERR_MEM) {
+ conn->err = ERR_OK;
+ sys_sem_wait(conn->sem);
+ } else {
+ goto ret;
+ }
+ }
+ ret:
+ memp_freep(MEMP_API_MSG, msg);
+ conn->state = NETCONN_NONE;
+ if(conn->sem != SYS_SEM_NULL) {
+ sys_sem_free(conn->sem);
+ conn->sem = SYS_SEM_NULL;
+ }
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_close(struct netconn *conn)
+{
+ struct api_msg *msg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+ if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
+ return (conn->err = ERR_MEM);
+ }
+
+ conn->state = NETCONN_CLOSE;
+ again:
+ msg->type = API_MSG_CLOSE;
+ msg->msg.conn = conn;
+ api_msg_post(msg);
+ sys_mbox_fetch(conn->mbox, NULL);
+ if(conn->err == ERR_MEM &&
+ conn->sem != SYS_SEM_NULL) {
+ sys_sem_wait(conn->sem);
+ goto again;
+ }
+ conn->state = NETCONN_NONE;
+ memp_freep(MEMP_API_MSG, msg);
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+netconn_err(struct netconn *conn)
+{
+ return conn->err;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
diff --git a/src/api/api_msg.c b/src/api/api_msg.c
new file mode 100644
index 0000000..a914ff3
--- /dev/null
+++ b/src/api/api_msg.c
@@ -0,0 +1,544 @@
+/*
+ * 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/arch.h"
+#include "lwip/api_msg.h"
+#include "lwip/memp.h"
+#include "lwip/sys.h"
+#include "lwip/tcpip.h"
+
+/*-----------------------------------------------------------------------------------*/
+static err_t
+recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+ struct netconn *conn;
+
+ conn = arg;
+
+ if(conn == NULL) {
+ pbuf_free(p);
+ return ERR_VAL;
+ }
+
+ if(conn->recvmbox != SYS_MBOX_NULL) {
+ conn->err = err;
+ sys_mbox_post(conn->recvmbox, p);
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_UDP
+static void
+recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
+ struct ip_addr *addr, u16_t port)
+{
+ struct netbuf *buf;
+ struct netconn *conn;
+
+ conn = arg;
+
+ if(conn == NULL) {
+ pbuf_free(p);
+ return;
+ }
+
+ if(conn->recvmbox != SYS_MBOX_NULL) {
+ buf = memp_mallocp(MEMP_NETBUF);
+ if(buf == NULL) {
+ pbuf_free(p);
+ return;
+ } else {
+ buf->p = p;
+ buf->ptr = p;
+ buf->fromaddr = addr;
+ buf->fromport = port;
+ }
+
+ sys_mbox_post(conn->recvmbox, buf);
+ }
+}
+#endif /* LWIP_UDP */
+/*-----------------------------------------------------------------------------------*/
+static err_t
+poll_tcp(void *arg, struct tcp_pcb *pcb)
+{
+ struct netconn *conn;
+
+ conn = arg;
+ if(conn != NULL &&
+ (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
+ conn->sem != SYS_SEM_NULL) {
+ sys_sem_signal(conn->sem);
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static err_t
+sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
+{
+ struct netconn *conn;
+
+ conn = arg;
+ if(conn != NULL && conn->sem != SYS_SEM_NULL) {
+ sys_sem_signal(conn->sem);
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+err_tcp(void *arg, err_t err)
+{
+ struct netconn *conn;
+
+ conn = arg;
+
+ conn->pcb.tcp = NULL;
+
+
+ conn->err = err;
+ if(conn->recvmbox != SYS_MBOX_NULL) {
+ sys_mbox_post(conn->recvmbox, NULL);
+ }
+ if(conn->mbox != SYS_MBOX_NULL) {
+ sys_mbox_post(conn->mbox, NULL);
+ }
+ if(conn->acceptmbox != SYS_MBOX_NULL) {
+ sys_mbox_post(conn->acceptmbox, NULL);
+ }
+ if(conn->sem != SYS_SEM_NULL) {
+ sys_sem_signal(conn->sem);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+setup_tcp(struct netconn *conn)
+{
+ struct tcp_pcb *pcb;
+
+ pcb = conn->pcb.tcp;
+ tcp_arg(pcb, conn);
+ tcp_recv(pcb, recv_tcp);
+ tcp_sent(pcb, sent_tcp);
+ tcp_poll(pcb, poll_tcp, 4);
+ tcp_err(pcb, err_tcp);
+}
+/*-----------------------------------------------------------------------------------*/
+static err_t
+accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
+{
+ sys_mbox_t *mbox;
+ struct netconn *newconn;
+
+#if API_MSG_DEBUG
+#if TCP_DEBUG
+ tcp_debug_print_state(newpcb->state);
+#endif /* TCP_DEBUG */
+#endif /* API_MSG_DEBUG */
+ mbox = (sys_mbox_t *)arg;
+ newconn = memp_mallocp(MEMP_NETCONN);
+ if(newconn == NULL) {
+ return ERR_MEM;
+ }
+ newconn->type = NETCONN_TCP;
+ newconn->pcb.tcp = newpcb;
+ setup_tcp(newconn);
+ newconn->recvmbox = sys_mbox_new();
+ if(newconn->recvmbox == SYS_MBOX_NULL) {
+ memp_free(MEMP_NETCONN, newconn);
+ return ERR_MEM;
+ }
+ newconn->mbox = sys_mbox_new();
+ if(newconn->mbox == SYS_MBOX_NULL) {
+ sys_mbox_free(newconn->recvmbox);
+ memp_free(MEMP_NETCONN, newconn);
+ return ERR_MEM;
+ }
+ newconn->sem = sys_sem_new(0);
+ if(newconn->sem == SYS_SEM_NULL) {
+ sys_mbox_free(newconn->recvmbox);
+ sys_mbox_free(newconn->mbox);
+ memp_free(MEMP_NETCONN, newconn);
+ return ERR_MEM;
+ }
+ newconn->acceptmbox = SYS_MBOX_NULL;
+ newconn->err = err;
+ sys_mbox_post(*mbox, newconn);
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_newconn(struct api_msg_msg *msg)
+{
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_delconn(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ msg->conn->pcb.udp->recv_arg = NULL;
+ udp_remove(msg->conn->pcb.udp);
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ if(msg->conn->pcb.tcp->state == LISTEN) {
+ tcp_accept(msg->conn->pcb.tcp, NULL);
+ tcp_close(msg->conn->pcb.tcp);
+ } else {
+ tcp_arg(msg->conn->pcb.tcp, NULL);
+ tcp_sent(msg->conn->pcb.tcp, NULL);
+ tcp_recv(msg->conn->pcb.tcp, NULL);
+ tcp_poll(msg->conn->pcb.tcp, NULL, 0);
+ tcp_err(msg->conn->pcb.tcp, NULL);
+ if(tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
+ tcp_abort(msg->conn->pcb.tcp);
+ }
+ }
+ break;
+ }
+ }
+ if(msg->conn->mbox != SYS_MBOX_NULL) {
+ sys_mbox_post(msg->conn->mbox, NULL);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_bind(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp == NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ msg->conn->pcb.udp = udp_new();
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+ case NETCONN_UDPNOCHKSUM:
+ msg->conn->pcb.udp = udp_new();
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+ case NETCONN_UDP:
+ msg->conn->pcb.udp = udp_new();
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ msg->conn->pcb.tcp = tcp_new();
+ setup_tcp(msg->conn);
+ break;
+ }
+ }
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
+ msg->msg.bc.ipaddr, msg->msg.bc.port);
+ break;
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+static err_t
+do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
+{
+ struct netconn *conn;
+
+ conn = arg;
+
+ if(conn == NULL) {
+ return ERR_VAL;
+ }
+
+ conn->err = err;
+
+ if(conn->type == NETCONN_TCP && err == ERR_OK) {
+ setup_tcp(conn);
+ }
+
+ sys_mbox_post(conn->mbox, NULL);
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_connect(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp == NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ msg->conn->pcb.udp = udp_new();
+ if(msg->conn->pcb.udp == NULL) {
+ msg->conn->err = ERR_MEM;
+ sys_mbox_post(msg->conn->mbox, NULL);
+ return;
+ }
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+ case NETCONN_UDPNOCHKSUM:
+ msg->conn->pcb.udp = udp_new();
+ if(msg->conn->pcb.udp == NULL) {
+ msg->conn->err = ERR_MEM;
+ sys_mbox_post(msg->conn->mbox, NULL);
+ return;
+ }
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+ case NETCONN_UDP:
+ msg->conn->pcb.udp = udp_new();
+ if(msg->conn->pcb.udp == NULL) {
+ msg->conn->err = ERR_MEM;
+ sys_mbox_post(msg->conn->mbox, NULL);
+ return;
+ }
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ msg->conn->pcb.tcp = tcp_new();
+ if(msg->conn->pcb.tcp == NULL) {
+ msg->conn->err = ERR_MEM;
+ sys_mbox_post(msg->conn->mbox, NULL);
+ return;
+ }
+ break;
+ }
+ }
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+ sys_mbox_post(msg->conn->mbox, NULL);
+ break;
+#endif
+ case NETCONN_TCP:
+ /* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
+ setup_tcp(msg->conn);
+ tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
+ do_connected);
+ /*tcp_output(msg->conn->pcb.tcp);*/
+ break;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_listen(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
+ if(msg->conn->pcb.tcp == NULL) {
+ msg->conn->err = ERR_MEM;
+ } else {
+ if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
+ msg->conn->acceptmbox = sys_mbox_new();
+ if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
+ msg->conn->err = ERR_MEM;
+ break;
+ }
+ }
+ tcp_arg(msg->conn->pcb.tcp, (void *)&(msg->conn->acceptmbox));
+ tcp_accept(msg->conn->pcb.tcp, accept_function);
+ }
+ break;
+ }
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_accept(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ break;
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_send(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ udp_send(msg->conn->pcb.udp, msg->msg.p);
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ break;
+ }
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_recv(struct api_msg_msg *msg)
+{
+ if(msg->conn->pcb.tcp != NULL) {
+ if(msg->conn->type == NETCONN_TCP) {
+ tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
+ }
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_write(struct api_msg_msg *msg)
+{
+ err_t err;
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ msg->conn->err = ERR_VAL;
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
+ msg->msg.w.len, msg->msg.w.copy);
+ /* This is the Nagle algorithm: inhibit the sending of new TCP
+ segments when new outgoing data arrives from the user if any
+ previously transmitted data on the connection remains
+ unacknowledged. */
+ if(err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) {
+ tcp_output(msg->conn->pcb.tcp);
+ }
+ msg->conn->err = err;
+ break;
+ }
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+do_close(struct api_msg_msg *msg)
+{
+ err_t err;
+ if(msg->conn->pcb.tcp != NULL) {
+ switch(msg->conn->type) {
+#if LWIP_UDP
+ case NETCONN_UDPLITE:
+ /* FALLTHROUGH */
+ case NETCONN_UDPNOCHKSUM:
+ /* FALLTHROUGH */
+ case NETCONN_UDP:
+ break;
+#endif /* LWIP_UDP */
+ case NETCONN_TCP:
+ if(msg->conn->pcb.tcp->state == LISTEN) {
+ err = tcp_close(msg->conn->pcb.tcp);
+ }
+ msg->conn->err = err;
+ break;
+ }
+ }
+ sys_mbox_post(msg->conn->mbox, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+typedef void (* api_msg_decode)(struct api_msg_msg *msg);
+static api_msg_decode decode[API_MSG_MAX] = {
+ do_newconn,
+ do_delconn,
+ do_bind,
+ do_connect,
+ do_listen,
+ do_accept,
+ do_send,
+ do_recv,
+ do_write,
+ do_close
+ };
+void
+api_msg_input(struct api_msg *msg)
+{
+ decode[msg->type](&(msg->msg));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+api_msg_post(struct api_msg *msg)
+{
+ tcpip_apimsg(msg);
+}
+/*-----------------------------------------------------------------------------------*/
+
+
diff --git a/src/api/err.c b/src/api/err.c
new file mode 100644
index 0000000..b9aca8d
--- /dev/null
+++ b/src/api/err.c
@@ -0,0 +1,59 @@
+/*
+ * 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/err.h"
+
+#ifdef LWIP_DEBUG
+
+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."
+};
+
+/*-----------------------------------------------------------------------------------*/
+char *
+lwip_strerr(err_t err)
+{
+ return err_strerr[-err];
+
+}
+/*-----------------------------------------------------------------------------------*/
+
+#endif /* LWIP_DEBUG */
diff --git a/src/api/sockets.c b/src/api/sockets.c
new file mode 100644
index 0000000..93761c0
--- /dev/null
+++ b/src/api/sockets.c
@@ -0,0 +1,441 @@
+/*
+ * 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/api.h"
+
+#include "lwip/sockets.h"
+
+#define NUM_SOCKETS 10
+
+struct lwip_socket {
+ struct netconn *conn;
+ struct netbuf *lastdata;
+ u16_t lastoffset;
+};
+
+static struct lwip_socket sockets[NUM_SOCKETS];
+
+/*-----------------------------------------------------------------------------------*/
+static struct lwip_socket *
+get_socket(int s)
+{
+ struct lwip_socket *sock;
+
+ if(s > NUM_SOCKETS) {
+ /* errno = EBADF; */
+ return NULL;
+ }
+
+ sock = &sockets[s];
+
+ if(sock->conn == NULL) {
+ /* errno = EBADF; */
+ return NULL;
+ }
+ return sock;
+}
+/*-----------------------------------------------------------------------------------*/
+static int
+alloc_socket(struct netconn *newconn)
+{
+ int i;
+
+ /* allocate a new socket identifier */
+ for(i = 0; i < NUM_SOCKETS; ++i) {
+ if(sockets[i].conn == NULL) {
+ sockets[i].conn = newconn;
+ sockets[i].lastdata = NULL;
+ sockets[i].lastoffset = 0;
+ return i;
+ }
+ }
+ return -1;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_accept(int s, struct sockaddr *addr, int *addrlen)
+{
+ struct lwip_socket *sock;
+ struct netconn *newconn;
+ struct ip_addr *naddr;
+ u16_t port;
+ int newsock;
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ newconn = netconn_accept(sock->conn);
+
+ /* get the IP address and port of the remote host */
+ netconn_peer(newconn, &naddr, &port);
+
+ ((struct sockaddr_in *)addr)->sin_addr.s_addr = naddr->addr;
+ ((struct sockaddr_in *)addr)->sin_port = port;
+
+ newsock = alloc_socket(newconn);
+ if(newsock == -1) {
+ netconn_delete(newconn);
+ /* errno = ENOBUFS; */
+ }
+ return newsock;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_bind(int s, struct sockaddr *name, int namelen)
+{
+ struct lwip_socket *sock;
+ struct ip_addr remote_addr;
+ u16_t remote_port;
+ err_t err;
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
+ remote_port = ((struct sockaddr_in *)name)->sin_port;
+
+ err = netconn_bind(sock->conn, &remote_addr, ntohs(remote_port));
+
+ if(err != ERR_OK) {
+ /* errno = ... */
+ return -1;
+ }
+
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_close(int s)
+{
+ struct lwip_socket *sock;
+
+ DEBUGF(SOCKETS_DEBUG, ("close: socket %d\n", s));
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+
+ netconn_delete(sock->conn);
+ if(sock->lastdata != NULL) {
+ netbuf_delete(sock->lastdata);
+ }
+ sock->lastdata = NULL;
+ sock->lastoffset = 0;
+ sock->conn = NULL;
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_connect(int s, struct sockaddr *name, int namelen)
+{
+ struct lwip_socket *sock;
+ struct ip_addr remote_addr;
+ u16_t remote_port;
+ err_t err;
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
+ remote_port = ((struct sockaddr_in *)name)->sin_port;
+
+ err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
+
+ if(err != ERR_OK) {
+ /* errno = ... */
+ return -1;
+ }
+
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_listen(int s, int backlog)
+{
+ struct lwip_socket *sock;
+ err_t err;
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ err = netconn_listen(sock->conn);
+
+ if(err != ERR_OK) {
+ /* errno = ... */
+ return -1;
+ }
+
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen)
+{
+ struct lwip_socket *sock;
+ struct netbuf *buf;
+ u16_t buflen, copylen;
+ struct ip_addr *addr;
+ u16_t port;
+
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ /* Check if there is data left from the last recv operation. */
+ if(sock->lastdata != NULL) {
+ buf = sock->lastdata;
+ } else {
+ /* No data was left from the previous operation, so we try to get
+ some from the network. */
+ buf = netconn_recv(sock->conn);
+
+ if(buf == NULL) {
+ /* We should really do some error checking here. */
+ return 0;
+ }
+ }
+
+ buflen = netbuf_len(buf);
+
+ buflen -= sock->lastoffset;
+
+ if(len > buflen) {
+ copylen = buflen;
+ } else {
+ copylen = len;
+ }
+
+ /* copy the contents of the received buffer into
+ the supplied memory pointer mem */
+ netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
+
+ /* If this is a TCP socket, check if there is data left in the
+ buffer. If so, it should be saved in the sock structure for next
+ time around. */
+ if(netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {
+ sock->lastdata = buf;
+ sock->lastoffset += copylen;
+ } else {
+ sock->lastdata = NULL;
+ sock->lastoffset = 0;
+ netbuf_delete(buf);
+ }
+
+ /* Check to see from where the data was. */
+ if(from != NULL && fromlen != NULL) {
+ addr = netbuf_fromaddr(buf);
+ port = netbuf_fromport(buf);
+ ((struct sockaddr_in *)from)->sin_addr.s_addr = addr->addr;
+ ((struct sockaddr_in *)from)->sin_port = port;
+ *fromlen = sizeof(struct sockaddr_in);
+ }
+
+
+ /* if the length of the received data is larger than
+ len, this data is discarded and we return len.
+ otherwise we return the actual length of the received
+ data */
+ if(len > copylen) {
+ return copylen;
+ } else {
+ return len;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_read(int s, void *mem, int len)
+{
+ return lwip_recv(s, mem, len, 0);
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_recv(int s, void *mem, int len, unsigned int flags)
+{
+ return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_send(int s, void *data, int size, unsigned int flags)
+{
+ struct lwip_socket *sock;
+ struct netbuf *buf;
+ err_t err;
+
+ DEBUGF(SOCKETS_DEBUG, ("send: socket %d, size %d\n", s, size));
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ switch(netconn_type(sock->conn)) {
+ case NETCONN_UDP:
+ /* create a buffer */
+ buf = netbuf_new();
+
+ if(buf == NULL) {
+ /* errno = ENOBUFS; */
+ return -1;
+ }
+
+ /* make the buffer point to the data that should
+ be sent */
+ netbuf_ref(buf, data, size);
+
+ /* send the data */
+ err = netconn_send(sock->conn, buf);
+
+ /* deallocated the buffer */
+ netbuf_delete(buf);
+ break;
+ case NETCONN_TCP:
+ err = netconn_write(sock->conn, data, size, NETCONN_COPY);
+ break;
+ default:
+ err = ERR_ARG;
+ break;
+ }
+ if(err != ERR_OK) {
+ /* errno = ... */
+ return -1;
+ }
+
+ return size;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_sendto(int s, void *data, int size, unsigned int flags,
+ struct sockaddr *to, int tolen)
+{
+ struct lwip_socket *sock;
+ struct ip_addr remote_addr, *addr;
+ u16_t remote_port, port;
+ int ret;
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ /* get the peer if currently connected */
+ netconn_peer(sock->conn, &addr, &port);
+
+ remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
+ remote_port = ((struct sockaddr_in *)to)->sin_port;
+ netconn_connect(sock->conn, &remote_addr, remote_port);
+
+ ret = lwip_send(s, data, size, flags);
+
+ /* reset the remote address and port number
+ of the connection */
+ netconn_connect(sock->conn, addr, port);
+ return ret;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_socket(int domain, int type, int protocol)
+{
+ struct netconn *conn;
+ int i;
+
+ /* create a netconn */
+ switch(type) {
+ case SOCK_DGRAM:
+ conn = netconn_new(NETCONN_UDP);
+ break;
+ case SOCK_STREAM:
+ conn = netconn_new(NETCONN_TCP);
+ break;
+ default:
+ /* errno = ... */
+ return -1;
+ }
+
+ if(conn == NULL) {
+ DEBUGF(SOCKETS_DEBUG, ("socket: could not create netconn.\n"));
+ /* errno = ENOBUFS; */
+ return -1;
+ }
+
+ i = alloc_socket(conn);
+
+ if(i == -1) {
+ /* errno = ENOBUFS; */
+ netconn_delete(conn);
+ }
+ return i;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+lwip_write(int s, void *data, int size)
+{
+ struct lwip_socket *sock;
+ err_t err;
+
+ DEBUGF(SOCKETS_DEBUG, ("write: socket %d, size %d\n", s, size));
+
+ sock = get_socket(s);
+ if(sock == NULL) {
+ return -1;
+ }
+
+ switch(netconn_type(sock->conn)) {
+ case NETCONN_UDP:
+ return lwip_send(s, data, size, 0);
+
+ case NETCONN_TCP:
+ err = netconn_write(sock->conn, data, size, NETCONN_COPY);
+ break;
+ default:
+ err = ERR_ARG;
+ break;
+ }
+ if(err != ERR_OK) {
+ /* errno = ... */
+ return -1;
+ }
+ return size;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/api/tcpip.c b/src/api/tcpip.c
new file mode 100644
index 0000000..bc3fd2c
--- /dev/null
+++ b/src/api/tcpip.c
@@ -0,0 +1,137 @@
+/*
+ * 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/opt.h"
+
+#include "lwip/sys.h"
+
+#include "lwip/memp.h"
+#include "lwip/pbuf.h"
+
+#include "lwip/ip.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "lwip/tcpip.h"
+
+static void (* tcpip_init_done)(void *arg) = NULL;
+static void *tcpip_init_done_arg;
+static sys_mbox_t mbox;
+
+/*-----------------------------------------------------------------------------------*/
+static void
+tcpip_tcp_timer(void *arg)
+{
+ tcp_tmr();
+ sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+
+static void
+tcpip_thread(void *arg)
+{
+ struct tcpip_msg *msg;
+
+ ip_init();
+ udp_init();
+ tcp_init();
+
+ 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 */
+ sys_mbox_fetch(mbox, (void *)&msg);
+ switch(msg->type) {
+ case TCPIP_MSG_API:
+ DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", msg));
+ api_msg_input(msg->msg.apimsg);
+ break;
+ 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;
+ default:
+ break;
+ }
+ memp_freep(MEMP_TCPIP_MSG, msg);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcpip_input(struct pbuf *p, struct netif *inp)
+{
+ struct tcpip_msg *msg;
+
+ msg = memp_mallocp(MEMP_TCPIP_MSG);
+ if(msg == NULL) {
+ pbuf_free(p);
+ return ERR_MEM;
+ }
+
+ msg->type = TCPIP_MSG_INPUT;
+ msg->msg.inp.p = p;
+ msg->msg.inp.netif = inp;
+ sys_mbox_post(mbox, msg);
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcpip_apimsg(struct api_msg *apimsg)
+{
+ 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);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcpip_init(void (* initfunc)(void *), void *arg)
+{
+ tcpip_init_done = initfunc;
+ tcpip_init_done_arg = arg;
+ mbox = sys_mbox_new();
+ sys_thread_new((void *)tcpip_thread, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
diff --git a/src/arch/6502/README b/src/arch/6502/README
new file mode 100644
index 0000000..2e24900
--- /dev/null
+++ b/src/arch/6502/README
@@ -0,0 +1 @@
+The 6502 code is far from complete.
diff --git a/src/arch/6502/include/arch/cc.h b/src/arch/6502/include/arch/cc.h
new file mode 100644
index 0000000..3f88973
--- /dev/null
+++ b/src/arch/6502/include/arch/cc.h
@@ -0,0 +1,47 @@
+/*
+ * 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 __CC_H__
+#define __CC_H__
+
+typedef unsigned char u8_t;
+typedef signed char s8_t;
+typedef unsigned short u16_t;
+typedef signed short s16_t;
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+#endif /* __CC_H__ */
diff --git a/src/arch/6502/include/arch/cpu.h b/src/arch/6502/include/arch/cpu.h
new file mode 100644
index 0000000..4439e1c
--- /dev/null
+++ b/src/arch/6502/include/arch/cpu.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __CPU_H__
+#define __CPU_H__
+
+#define BYTE_ORDER LITTLE_ENDIAN
+
+#endif /* __CPU_H__ */
diff --git a/src/arch/6502/include/arch/lib.h b/src/arch/6502/include/arch/lib.h
new file mode 100644
index 0000000..89d1c4a
--- /dev/null
+++ b/src/arch/6502/include/arch/lib.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __LIB_H__
+#define __LIB_H__
+
+int strlen(const char *str);
+int strncmp(const char *str1, const char *str2, int len);
+void bcopy(const void *src, void *dest, int len);
+void bzero(void *data, int n);
+
+#endif /* __LIB_H__ */
diff --git a/src/arch/6502/include/arch/perf.h b/src/arch/6502/include/arch/perf.h
new file mode 100644
index 0000000..55a1ff4
--- /dev/null
+++ b/src/arch/6502/include/arch/perf.h
@@ -0,0 +1,38 @@
+/*
+ * 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 __PERF_H__
+#define __PERF_H__
+
+#define PERF_START /* null definition */
+#define PERF_STOP(x) /* null definition */
+
+#endif /* __PERF_H__ */
diff --git a/src/arch/6502/include/arch/sys_arch.h b/src/arch/6502/include/arch/sys_arch.h
new file mode 100644
index 0000000..99a2492
--- /dev/null
+++ b/src/arch/6502/include/arch/sys_arch.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __SYS_C64_H__
+#define __SYS_C64_H__
+
+#define SYS_MBOX_NULL 0
+
+typedef int sys_sem_t;
+typedef int sys_mbox_t;
+typedef int sys_thread_t;
+
+#endif /* __SYS_C64_H__ */
diff --git a/src/arch/6502/lib_arch.c b/src/arch/6502/lib_arch.c
new file mode 100644
index 0000000..a523166
--- /dev/null
+++ b/src/arch/6502/lib_arch.c
@@ -0,0 +1,63 @@
+/*
+ * 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>
+ *
+ */
+
+/* These are generic implementations of various library functions used
+ * throughout the lwIP code. When porting, those should be optimized
+ * for the particular processor architecture, preferably coded in
+ * assembler.
+ */
+
+#include "lwip/arch.h"
+
+/*-----------------------------------------------------------------------------------*/
+void
+bcopy(const void *src, void *dst, unsigned int size)
+{
+ char *csrc, *cdst;
+ unsigned int i;
+
+ csrc = (char *)src;
+ cdst = dst;
+
+ for(i = 0; i < size; ++i) {
+ cdst[i] = csrc[i];
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+bzero(void *s, int n)
+{
+ for(--n ;n >= 0; --n) {
+ ((char *)s)[n] = 0;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/6502/sys_c64.c b/src/arch/6502/sys_c64.c
new file mode 100644
index 0000000..eeb639a
--- /dev/null
+++ b/src/arch/6502/sys_c64.c
@@ -0,0 +1,120 @@
+/*
+ * 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 <c64.h>
+#include <time.h>
+
+#include "lwip/sys.h"
+#include "lwip/def.h"
+
+struct sys_timeouts timeouts;
+
+/*-----------------------------------------------------------------------------------*/
+void
+sys_arch_block(u16_t time)
+{
+ u16_t ticks;
+
+ ticks = time * (CLK_TCK / 1000) + clock();
+ printf("ticks %d\n", ticks);
+
+ while(clock() != ticks);
+}
+/*-----------------------------------------------------------------------------------*/
+sys_mbox_t
+sys_mbox_new(void)
+{
+ return SYS_MBOX_NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_free(sys_mbox_t mbox)
+{
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_post(sys_mbox_t mbox, void *data)
+{
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u16_t timeout)
+{
+ sys_arch_block(timeout);
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+sys_sem_t
+sys_sem_new(u8_t count)
+{
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_sem_wait(sys_sem_t sem, u16_t timeout)
+{
+ sys_arch_block(timeout);
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_signal(sys_sem_t sem)
+{
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_free(sys_sem_t sem)
+{
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_init(void)
+{
+ timeouts.next = NULL;
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_timeouts *
+sys_arch_timeouts(void)
+{
+ return &timeouts;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_thread_new(void (* function)(void *arg), void *arg)
+{
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/FILES b/src/arch/FILES
new file mode 100644
index 0000000..7c6fd55
--- /dev/null
+++ b/src/arch/FILES
@@ -0,0 +1,15 @@
+6502/ - Architectural files for the 6502 CPU.
+
+rtxc/ - Architectural files for the RTXC operating system.
+
+unix/ - Architectural files for testing on unix-like systems
+ (assuming gcc and pthreads).
+
+Each subdirectory (may) also include:
+
+perf.c - Optional file that should be implemented when running
+ performance tests of lwIP.
+
+sys.c - Implementation of the operating system emulation layer.
+
+netif/ - Architectural specific network interfaces.
diff --git a/src/arch/rtxc/include/arch/cc.h b/src/arch/rtxc/include/arch/cc.h
new file mode 100644
index 0000000..3f88973
--- /dev/null
+++ b/src/arch/rtxc/include/arch/cc.h
@@ -0,0 +1,47 @@
+/*
+ * 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 __CC_H__
+#define __CC_H__
+
+typedef unsigned char u8_t;
+typedef signed char s8_t;
+typedef unsigned short u16_t;
+typedef signed short s16_t;
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+#endif /* __CC_H__ */
diff --git a/src/arch/rtxc/include/arch/cpu.h b/src/arch/rtxc/include/arch/cpu.h
new file mode 100644
index 0000000..4439e1c
--- /dev/null
+++ b/src/arch/rtxc/include/arch/cpu.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __CPU_H__
+#define __CPU_H__
+
+#define BYTE_ORDER LITTLE_ENDIAN
+
+#endif /* __CPU_H__ */
diff --git a/src/arch/rtxc/include/arch/init.h b/src/arch/rtxc/include/arch/init.h
new file mode 100644
index 0000000..dfcb98d
--- /dev/null
+++ b/src/arch/rtxc/include/arch/init.h
@@ -0,0 +1,44 @@
+/*
+ * 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 __ARCH_INIT_H__
+#define __ARCH_INIT_H__
+
+#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg)
+
+void tcpip_init_done(void *);
+int wait_for_tcpip_init(void);
+
+#endif /* __ARCH_INIT_H__ */
+
+
+
+
diff --git a/src/arch/rtxc/include/arch/lib.h b/src/arch/rtxc/include/arch/lib.h
new file mode 100644
index 0000000..ef36c98
--- /dev/null
+++ b/src/arch/rtxc/include/arch/lib.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __LIB_H__
+#define __LIB_H__
+
+#include <string.h>
+
+#define bcopy(s, d, l) memcpy(d, s, l)
+#define bzero(d, l) memset(d, 0, l)
+
+#endif /* __LIB_H__ */
diff --git a/src/arch/rtxc/include/arch/perf.h b/src/arch/rtxc/include/arch/perf.h
new file mode 100644
index 0000000..55a1ff4
--- /dev/null
+++ b/src/arch/rtxc/include/arch/perf.h
@@ -0,0 +1,38 @@
+/*
+ * 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 __PERF_H__
+#define __PERF_H__
+
+#define PERF_START /* null definition */
+#define PERF_STOP(x) /* null definition */
+
+#endif /* __PERF_H__ */
diff --git a/src/arch/rtxc/include/arch/sys_arch.h b/src/arch/rtxc/include/arch/sys_arch.h
new file mode 100644
index 0000000..a685e2e
--- /dev/null
+++ b/src/arch/rtxc/include/arch/sys_arch.h
@@ -0,0 +1,45 @@
+/*
+ * 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 __SYS_RTXC_H__
+#define __SYS_RTXC_H__
+
+#include "rtxcapi.h"
+
+#define SYS_MBOX_NULL (QUEUE)0
+#define SYS_SEM_NULL (SEMA)0
+
+typedef SEMA sys_sem_t;
+typedef QUEUE sys_mbox_t;
+typedef TASK sys_thread_t;
+
+#endif /* __SYS_RTXC_H__ */
+
diff --git a/src/arch/rtxc/include/netif/cs8900if.h b/src/arch/rtxc/include/netif/cs8900if.h
new file mode 100644
index 0000000..46440db
--- /dev/null
+++ b/src/arch/rtxc/include/netif/cs8900if.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __NETIF_CS8900IF_H__
+#define __NETIF_CS8900IF_H__
+
+#include "lwip/netif.h"
+
+void cs8900if_init(struct netif *);
+u8_t cs8900if_poll(struct netif *);
+void cs8900if_input(struct netif *);
+
+#endif /* __NETIF_CS8900IF_H__ */
diff --git a/src/arch/rtxc/include/netif/sioslipif.h b/src/arch/rtxc/include/netif/sioslipif.h
new file mode 100644
index 0000000..a22fd98
--- /dev/null
+++ b/src/arch/rtxc/include/netif/sioslipif.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __NETIF_SIOSLIPIF_H__
+#define __NETIF_SIOSLIPIF_H__
+
+#include "lwip/netif.h"
+
+void sioslipif_init(struct netif *);
+
+#endif /* __NETIF_SIOSLIPIF_H__ */
diff --git a/src/arch/rtxc/lib.c b/src/arch/rtxc/lib.c
new file mode 100644
index 0000000..726f0c6
--- /dev/null
+++ b/src/arch/rtxc/lib.c
@@ -0,0 +1,63 @@
+/*
+ * 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>
+ *
+ */
+
+/* These are generic implementations of various library functions used
+ * throughout the lwIP code. When porting, those should be optimized
+ * for the particular processor architecture, preferably coded in
+ * assembler.
+ */
+
+#if 0 /* Define to 1 if these are really needed. */
+/*-----------------------------------------------------------------------------------*/
+void
+bcopy(const void *src, void *dst, unsigned int size)
+{
+ char *csrc, *cdst;
+ unsigned int i;
+
+ csrc = (char *)src;
+ cdst = dst;
+
+ for(i = 0; i < size; ++i) {
+ cdst[i] = csrc[i];
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+bzero(void *s, int n)
+{
+ for(--n ;n >= 0; --n) {
+ ((char *)s)[n] = 0;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+#endif /* 0 */
diff --git a/src/arch/rtxc/netif/FILES b/src/arch/rtxc/netif/FILES
new file mode 100644
index 0000000..1b009e8
--- /dev/null
+++ b/src/arch/rtxc/netif/FILES
@@ -0,0 +1 @@
+sioslipif.c - Implementation of the SLIP protocol on top of a serial line.
diff --git a/src/arch/rtxc/netif/sioslipif.c b/src/arch/rtxc/netif/sioslipif.c
new file mode 100644
index 0000000..8a09e6e
--- /dev/null
+++ b/src/arch/rtxc/netif/sioslipif.c
@@ -0,0 +1,170 @@
+/*
+ * 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/def.h"
+#include "netif/sioslipif.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#define SLIP_END 0300
+#define SLIP_ESC 0333
+#define SLIP_ESC_END 0334
+#define SLIP_ESC_ESC 0335
+
+/* This variable is used for passing the netif pointer between the
+ threads. */
+static struct netif *netif_pass;
+
+static int infd, outfd;
+/*-----------------------------------------------------------------------------------*/
+static void
+sio_send(u8_t c)
+{
+ write(outfd, &c, 1);
+}
+/*-----------------------------------------------------------------------------------*/
+static u8_t
+sio_recv(void)
+{
+ u8_t c;
+ read(infd, &c, 1);
+ return c;
+}
+/*-----------------------------------------------------------------------------------*/
+static int
+sioslipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
+{
+ struct pbuf *q;
+ int i;
+ u8_t c;
+
+ /* Send pbuf out on the serial I/O device. */
+ sio_send(SLIP_END);
+
+ for(q = p; q != NULL; q = q->next) {
+ for(i = 0; i < q->len; i++) {
+ c = ((u8_t *)q->payload)[i];
+ switch(c) {
+ case SLIP_END:
+ sio_send(SLIP_ESC);
+ sio_send(SLIP_ESC_END);
+ break;
+ case SLIP_ESC:
+ sio_send(SLIP_ESC);
+ sio_send(SLIP_ESC_ESC);
+ break;
+ default:
+ sio_send(c);
+ break;
+ }
+ }
+ }
+ sio_send(SLIP_END);
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+static struct pbuf *
+sioslipif_input(void)
+{
+ u8_t c;
+ struct pbuf *p, *q;
+ int recved;
+ int i;
+
+ p = pbuf_alloc(PBUF_LINK, PBUF_MAX_SIZE, PBUF_POOL);
+ q = p;
+ recved = i = 0;
+
+ while(1) {
+ c = sio_recv();
+ switch(c) {
+ case SLIP_END:
+ if(recved > 0) {
+ /* Received whole packet. */
+ pbuf_realloc(p, recved);
+ return p;
+ }
+ break;
+ case SLIP_ESC:
+ c = sio_recv();
+ switch(c) {
+ case SLIP_ESC_END:
+ c = SLIP_END;
+ break;
+ case SLIP_ESC_ESC:
+ c = SLIP_ESC;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if(recved < p->tot_len && q != NULL) {
+ ((u8_t *)q->payload)[i] = c;
+ recved++;
+ i++;
+ if(i >= q->len) {
+ i = 0;
+ q = q->next;
+ }
+ }
+ break;
+ }
+
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+sioslipif_loop(void)
+{
+ struct pbuf *p;
+ struct netif *netif;
+
+ netif = netif_pass;
+ while(1) {
+ p = sioslipif_input();
+ netif->input(p, netif);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sioslipif_init(struct netif *netif)
+{
+ netif->state = NULL;
+ netif->name[0] = 's';
+ netif->name[1] = 'l';
+ netif->output = sioslipif_output;
+
+ netif_pass = netif;
+ sys_thread_new((void *)sioslipif_loop, NULL);
+ /* Do some magic to make it possible to receive data from the serial I/O device. */
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/rtxc/perf.c b/src/arch/rtxc/perf.c
new file mode 100644
index 0000000..ebf167a
--- /dev/null
+++ b/src/arch/rtxc/perf.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "arch/perf.h"
+
+void
+perf_init(char *fname)
+{
+}
diff --git a/src/arch/rtxc/sys_arch.c b/src/arch/rtxc/sys_arch.c
new file mode 100644
index 0000000..4237142
--- /dev/null
+++ b/src/arch/rtxc/sys_arch.c
@@ -0,0 +1,271 @@
+/*
+ * 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/def.h"
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+
+#include "rtxcapi.h"
+#include "csema.h"
+#include "cclock.h"
+#include "cqueue.h"
+#include "cres.h"
+#include "cpart.h"
+#include "ctask.h"
+
+struct timeoutlist {
+ struct sys_timeouts timeouts;
+ TASK pid;
+};
+
+#define SYS_THREAD_MAX 2
+
+static struct timeoutlist timeoutlist[SYS_THREAD_MAX];
+static u16_t nextthread = 0;
+
+/*-----------------------------------------------------------------------------------*/
+sys_mbox_t
+sys_mbox_new(void)
+{
+ QUEUE mbox;
+ KS_dequeuew(IP_MBOXQ, &mbox);
+ KS_purgequeue(mbox);
+ return mbox;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_free(sys_mbox_t mbox)
+{
+ KS_enqueue(IP_MBOXQ, &mbox);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_post(sys_mbox_t mbox, void *data)
+{
+ if(KS_enqueue(mbox, &data) != RC_GOOD) {
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u16_t timeout)
+{
+ KSRC ret;
+ u16_t wtime = 1;
+
+ if(timeout == 0) {
+ DEBUGF(SYS_DEBUG, ("PID: %d sys_mbox_fetch: without timeouts\n",KS_inqtask()));
+ KS_dequeuew(mbox, data);
+
+ } else {
+
+ ret = KS_dequeuet(mbox, data, (TICKS)timeout/CLKTICK);
+ if(ret == RC_TIMEOUT) {
+ /* The call timed out, so we return 0. */
+ wtime = 0;
+ } else {
+ /* Calculate time we waited for the message to arrive. */
+
+ /* XXX: we cheat and just pretend that we waited for half the timeout value! */
+ wtime = timeout / 2;
+
+ /* Make sure we don't return 0 here. */
+ if(wtime == 0) {
+ wtime = 1;
+ }
+ }
+ }
+ return wtime;
+}
+/*-----------------------------------------------------------------------------------*/
+sys_sem_t
+sys_sem_new(u8_t count)
+{
+ SEMA sem;
+ KS_dequeuew(IP_SEMQ, &sem);
+ KS_pend(sem);
+ if(count > 0) {
+ KS_signal(sem);
+ }
+ return sem;
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_sem_wait(sys_sem_t sem, u16_t timeout)
+{
+ KSRC ret;
+ u16_t wtime = 1;
+
+ if(timeout == 0) {
+ DEBUGF(SYS_DEBUG, ("PID: %d sys_mbox_fetch: without timeouts\n",KS_inqtask()));
+ KS_wait(sem);
+
+ } else {
+ ret = KS_waitt(sem, (TICKS)timeout/CLKTICK);
+ if(ret == RC_TIMEOUT) {
+ /* The call timed out, so we return 0. */
+ wtime = 0;
+ } else {
+ /* Calculate time we waited for the message to arrive. */
+
+ /* XXX: we cheat and just pretend that we waited for half the timeout value! */
+ wtime = timeout / 2;
+
+ /* Make sure we don't return 0 here. */
+ if(wtime == 0) {
+ wtime = 1;
+ }
+ }
+ }
+ return wtime;
+
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_signal(sys_sem_t sem)
+{
+ KS_signal(sem);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_free(sys_sem_t sem)
+{
+ KS_enqueue(IP_SEMQ, &sem);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_init(void)
+{
+ /* posta in alla semaforer i IP_SEMQ, posta in alla mboxar i
+ IP_MBOXQ */
+ QUEUE mbox;
+ SEMA sem;
+
+ mbox = IP_Q_01; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_02; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_03; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_04; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_05; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_06; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_07; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_08; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_09; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_10; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_11; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_12; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_13; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_14; KS_enqueue(IP_MBOXQ, &mbox);
+ mbox = IP_Q_15; KS_enqueue(IP_MBOXQ, &mbox);
+ sem = IP_S_01; KS_enqueue(IP_SEMQ, &sem);
+ sem = IP_S_02; KS_enqueue(IP_SEMQ, &sem);
+ sem = IP_S_03; KS_enqueue(IP_SEMQ, &sem);
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_timeouts *
+sys_arch_timeouts(void)
+{
+ int i;
+ TASK pid;
+ struct timeoutlist *tl;
+
+ DEBUGF(SYS_DEBUG, ("PID: %d sys_mbox_fetch: timeoutlist not empty\n",KS_inqtask()));
+ pid = KS_inqtask();
+ for(i = 0; i < nextthread; i++) {
+ tl = &timeoutlist[i];
+ if(tl->pid == pid) {
+ DEBUGF(SYS_DEBUG, ("PID: %d sys_mbox_fetch: corresponding pid found!\n",KS_inqtask()));
+ return &(tl->timeouts);
+ }
+ }
+
+ /* Error! */
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_thread_arg {
+ void (* thread)(void *);
+ void *threadarg;
+ SEMA sem;
+};
+/*-----------------------------------------------------------------------------------*/
+static void
+sys_thread(void)
+{
+ struct sys_thread_arg *arg;
+ void (* thread)(void *);
+ void *threadarg;
+
+ arg = KS_inqtask_arg(0);
+ if(arg != NULL) {
+
+ timeoutlist[nextthread].timeouts.next = NULL;
+ timeoutlist[nextthread].pid = KS_inqtask();
+
+ ++nextthread;
+
+ thread = arg->thread;
+ threadarg = arg->threadarg;
+ KS_signal(arg->sem);
+ thread(threadarg);
+ }
+ KS_terminate(0);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_thread_new(void (* function)(void *arg), void *arg)
+{
+ TASK newtask;
+ PRIORITY pri = 2; /* This may have to be changed. */
+ char *stack;
+ int stacksize = 512; /* This may have to be changed. */
+ struct sys_thread_arg threadarg;
+
+
+ newtask = KS_alloc_task();
+ stack = KS_allocw(MAP512);
+
+ KS_deftask(newtask, pri, (char ks_stk *)stack, (size_t)stacksize, (void (*)(void))sys_thread);
+
+ threadarg.thread = function;
+ threadarg.threadarg = arg;
+ threadarg.sem = THRDSYNC;
+ KS_deftask_arg(newtask, &threadarg);
+ KS_execute(newtask);
+ KS_wait(THRDSYNC);
+}
+
+
+
+
+
+
diff --git a/src/arch/unix/include/arch/cc.h b/src/arch/unix/include/arch/cc.h
new file mode 100644
index 0000000..0197c8c
--- /dev/null
+++ b/src/arch/unix/include/arch/cc.h
@@ -0,0 +1,51 @@
+/*
+ * 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 __ARCH_CC_H__
+#define __ARCH_CC_H__
+
+typedef unsigned char u8_t;
+typedef signed char s8_t;
+/*typedef unsigned short u8_t;
+ typedef signed short s8_t; */
+typedef unsigned short u16_t;
+typedef signed short s16_t;
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+
+typedef u32_t mem_ptr_t;
+
+#define PACK_STRUCT_FIELD(x) x __attribute__((packed))
+#define PACK_STRUCT_STRUCT __attribute__((packed))
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_END
+
+#endif /* __ARCH_CC_H__ */
diff --git a/src/arch/unix/include/arch/cpu.h b/src/arch/unix/include/arch/cpu.h
new file mode 100644
index 0000000..ae3586e
--- /dev/null
+++ b/src/arch/unix/include/arch/cpu.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __ARCH_CPU_H__
+#define __ARCH_CPU_H__
+
+#ifndef BYTE_ORDER
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif /* BYTE_ORDER */
+
+#endif /* __ARCH_CPU_H__ */
diff --git a/src/arch/unix/include/arch/init.h b/src/arch/unix/include/arch/init.h
new file mode 100644
index 0000000..d6e3735
--- /dev/null
+++ b/src/arch/unix/include/arch/init.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __ARCH_INIT_H__
+#define __ARCH_INIT_H__
+
+#define TCPIP_INIT_DONE(arg) sys_sem_signal(*(sys_sem_t *)arg)
+
+#endif /* __ARCH_INIT_H__ */
+
+
+
+
diff --git a/src/arch/unix/include/arch/lib.h b/src/arch/unix/include/arch/lib.h
new file mode 100644
index 0000000..f739dea
--- /dev/null
+++ b/src/arch/unix/include/arch/lib.h
@@ -0,0 +1,44 @@
+/*
+ * 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 __ARCH_LIB_H__
+#define __ARCH_LIB_H__
+
+#ifndef _STRING_H_
+#ifndef _STRING_H
+int strlen(const char *str);
+int strncmp(const char *str1, const char *str2, int len);
+void bcopy(const void *src, void *dest, int len);
+void bzero(void *data, int n);
+#endif /* _STRING_H */
+#endif /* _STRING_H_ */
+
+#endif /* __ARCH_LIB_H__ */
diff --git a/src/arch/unix/include/arch/perf.h b/src/arch/unix/include/arch/perf.h
new file mode 100644
index 0000000..8d8e767
--- /dev/null
+++ b/src/arch/unix/include/arch/perf.h
@@ -0,0 +1,63 @@
+/*
+ * 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 __ARCH_PERF_H__
+#define __ARCH_PERF_H__
+
+#include <sys/times.h>
+
+#ifdef PERF
+#define PERF_START { \
+ unsigned long __c1l, __c1h, __c2l, __c2h; \
+ __asm__(".byte 0x0f, 0x31" : "=a" (__c1l), "=d" (__c1h))
+#define PERF_STOP(x) __asm__(".byte 0x0f, 0x31" : "=a" (__c2l), "=d" (__c2h)); \
+ perf_print(__c1l, __c1h, __c2l, __c2h, x);}
+
+/*#define PERF_START do { \
+ struct tms __perf_start, __perf_end; \
+ times(&__perf_start)
+#define PERF_STOP(x) times(&__perf_end); \
+ perf_print_times(&__perf_start, &__perf_end, x);\
+ } while(0)*/
+#else /* PERF */
+#define PERF_START /* null definition */
+#define PERF_STOP(x) /* null definition */
+#endif /* PERF */
+
+void perf_print(unsigned long c1l, unsigned long c1h,
+ unsigned long c2l, unsigned long c2h,
+ char *key);
+
+void perf_print_times(struct tms *start, struct tms *end, char *key);
+
+void perf_init(char *fname);
+
+#endif /* __ARCH_PERF_H__ */
diff --git a/src/arch/unix/include/arch/sys_arch.h b/src/arch/unix/include/arch/sys_arch.h
new file mode 100644
index 0000000..f85dd09
--- /dev/null
+++ b/src/arch/unix/include/arch/sys_arch.h
@@ -0,0 +1,48 @@
+/*
+ * 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 __ARCH_SYS_ARCH_H__
+#define __ARCH_SYS_ARCH_H__
+
+#define SYS_MBOX_NULL NULL
+#define SYS_SEM_NULL NULL
+
+struct sys_sem;
+typedef struct sys_sem * sys_sem_t;
+
+struct sys_mbox;
+typedef struct sys_mbox *sys_mbox_t;
+
+struct sys_thread;
+typedef struct sys_thread * sys_thread_t;
+
+#endif /* __ARCH_SYS_ARCH_H__ */
+
diff --git a/src/arch/unix/include/netif/delif.h b/src/arch/unix/include/netif/delif.h
new file mode 100644
index 0000000..9a7dbe7
--- /dev/null
+++ b/src/arch/unix/include/netif/delif.h
@@ -0,0 +1,42 @@
+/*
+ * 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 __DELIF_H__
+#define __DELIF_H__
+
+#include "lwip/netif.h"
+
+#include "lwip/pbuf.h"
+
+void delif_init(struct netif *netif);
+void delif_init_thread(struct netif *netif);
+
+#endif /* __DELIF_H__ */
diff --git a/src/arch/unix/include/netif/dropif.h b/src/arch/unix/include/netif/dropif.h
new file mode 100644
index 0000000..3e48dca
--- /dev/null
+++ b/src/arch/unix/include/netif/dropif.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __DROPIF_H__
+#define __DROPIF_H__
+
+#include "lwip/netif.h"
+
+#include "lwip/pbuf.h"
+
+void dropif_init(struct netif *netif);
+
+#endif /* __DROPIF_H__ */
diff --git a/src/arch/unix/include/netif/pcapif.h b/src/arch/unix/include/netif/pcapif.h
new file mode 100644
index 0000000..80c1a34
--- /dev/null
+++ b/src/arch/unix/include/netif/pcapif.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __PCAPIF_H__
+#define __PCAPIF_H__
+
+#include "lwip/netif.h"
+
+void pcapif_init(struct netif *netif);
+
+#endif /* __PCAPIF_H__ */
diff --git a/src/arch/unix/include/netif/sioslipif.h b/src/arch/unix/include/netif/sioslipif.h
new file mode 100644
index 0000000..ac31b0d
--- /dev/null
+++ b/src/arch/unix/include/netif/sioslipif.h
@@ -0,0 +1,43 @@
+/*
+ * 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 __NETIF_SIOSLIPIF_H__
+#define __NETIF_SIOSLIPIF_H__
+
+#include "lwip/netif.h"
+
+void sioslipif_init(struct netif *);
+
+
+void sioslipif_init1(struct netif *);
+void sioslipif_init2(struct netif *);
+
+#endif /* __NETIF_SIOSLIPIF_H__ */
diff --git a/src/arch/unix/include/netif/tapif.h b/src/arch/unix/include/netif/tapif.h
new file mode 100644
index 0000000..d434f55
--- /dev/null
+++ b/src/arch/unix/include/netif/tapif.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __TAPIF_H__
+#define __TAPIF_H__
+
+#include "lwip/netif.h"
+
+void tapif_init(struct netif *netif);
+
+#endif /* __TAPIF_H__ */
diff --git a/src/arch/unix/include/netif/tunif.h b/src/arch/unix/include/netif/tunif.h
new file mode 100644
index 0000000..ca7cada
--- /dev/null
+++ b/src/arch/unix/include/netif/tunif.h
@@ -0,0 +1,42 @@
+/*
+ * 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 __TUNIF_H__
+#define __TUNIF_H__
+
+#include "lwip/netif.h"
+
+#include "lwip/pbuf.h"
+
+void tunif_init(struct netif *netif);
+void tunif_init_thread(struct netif *netif);
+
+#endif /* __TUNIF_H__ */
diff --git a/src/arch/unix/include/netif/unixif.h b/src/arch/unix/include/netif/unixif.h
new file mode 100644
index 0000000..0e34fb1
--- /dev/null
+++ b/src/arch/unix/include/netif/unixif.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __UNIXIF_H__
+#define __UNIXIF_H__
+
+#include "lwip/netif.h"
+
+void unixif_init_server(struct netif *netif);
+void unixif_init_client(struct netif *netif);
+
+#endif /* __UNIXIF_H__ */
diff --git a/src/arch/unix/lwip_chksum.c b/src/arch/unix/lwip_chksum.c
new file mode 100644
index 0000000..480a013
--- /dev/null
+++ b/src/arch/unix/lwip_chksum.c
@@ -0,0 +1,73 @@
+/*
+ * 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/arch.h"
+
+#include "lwip/def.h"
+#include "lwip/inet.h"
+
+
+/*-----------------------------------------------------------------------------------*/
+/* lwip_chksum:
+ *
+ * Sums up all 16 bit words in a memory portion. Also includes any odd byte.
+ * This function is used by the other checksum functions.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#if 0
+u16_t
+lwip_chksum(void *dataptr, int len)
+{
+ u32_t acc;
+
+ for(acc = 0; len > 1; len -= 2) {
+ acc += *((u16_t *)dataptr)++;
+ }
+
+ /* add up any odd byte */
+ if(len == 1) {
+ acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
+ DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", *(u8_t *)dataptr));
+ }
+ acc = (acc >> 16) + (acc & 0xffffUL);
+
+ if(acc & 0xffff0000 != 0) {
+ acc = (acc >> 16) + (acc & 0xffffUL);
+ }
+
+ return (u16_t)acc;
+}
+/*-----------------------------------------------------------------------------------*/
+#endif
diff --git a/src/arch/unix/netif/delif.c b/src/arch/unix/netif/delif.c
new file mode 100644
index 0000000..0e41922
--- /dev/null
+++ b/src/arch/unix/netif/delif.c
@@ -0,0 +1,310 @@
+/*
+ * 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 <stdlib.h>
+
+#include "lwip/def.h"
+#include "netif/delif.h"
+
+#ifdef linux
+#include "netif/tapif.h"
+#else /* linux */
+#include "netif/tunif.h"
+#endif /* linux */
+
+#include "lwip/sys.h"
+
+
+#define DELIF_INPUT_DROPRATE 0.1
+#define DELIF_OUTPUT_DROPRATE 0.1
+
+#define DELIF_INPUT_DELAY 500 /* Miliseconds. */
+#define DELIF_OUTPUT_DELAY 500 /* Miliseconds. */
+
+#define DELIF_TIMEOUT 10
+
+struct delif {
+ err_t (* input)(struct pbuf *p, struct netif *inp);
+ struct netif *netif;
+};
+
+struct delif_pbuf {
+ struct delif_pbuf *next;
+ struct pbuf *p;
+ struct ip_addr *ipaddr;
+ unsigned int time;
+};
+
+static struct delif_pbuf *input_list = NULL;
+static struct delif_pbuf *output_list = NULL;
+/*-----------------------------------------------------------------------------------*/
+static void
+delif_input_timeout(void *arg)
+{
+ struct netif *netif;
+ struct delif *delif;
+ struct delif_pbuf *dp;
+ unsigned int timeout, now;
+
+ timeout = DELIF_TIMEOUT;
+
+ netif = arg;
+ delif = netif->state;
+
+
+ /* Check if there is anything on the input list. */
+ dp = input_list;
+ while(dp != NULL) {
+ now = sys_now();
+
+ if(dp->time <= now) {
+ delif->input(dp->p, netif);
+ if(dp->next != NULL) {
+ if(dp->next->time > now) {
+ timeout = dp->next->time - now;
+ } else {
+ timeout = 0;
+ }
+ DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout));
+
+ }
+ input_list = dp->next;
+ free(dp);
+ dp = input_list;
+ } else {
+ dp = dp->next;
+ }
+ }
+
+ sys_timeout(timeout, delif_input_timeout, arg);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+delif_output_timeout(void *arg)
+{
+ struct netif *netif;
+ struct delif *delif;
+ struct delif_pbuf *dp;
+ unsigned int timeout, now;
+
+ timeout = DELIF_TIMEOUT;
+
+ netif = arg;
+ delif = netif->state;
+
+ /* Check if there is anything on the output list. */
+ dp = output_list;
+ while(dp != NULL) {
+ now = sys_now();
+ if(dp->time <= now) {
+ DEBUGF(DELIF_DEBUG, ("delif_output_timeout: now %u dp->time %u\n",
+ now, dp->time));
+ delif->netif->output(delif->netif, dp->p, dp->ipaddr);
+ if(dp->next != NULL) {
+ if(dp->next->time > now) {
+ timeout = dp->next->time - now;
+ } else {
+ timeout = 0;
+ }
+ DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout));
+
+ }
+ pbuf_free(dp->p);
+
+ output_list = dp->next;
+ free(dp);
+ dp = output_list;
+ } else {
+ dp = dp->next;
+ }
+ }
+
+
+ sys_timeout(timeout, delif_output_timeout, arg);
+}
+/*-----------------------------------------------------------------------------------*/
+static err_t
+delif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
+{
+ struct delif_pbuf *dp, *np;
+ struct pbuf *q;
+ int i, j;
+ char *data;
+
+ DEBUGF(DELIF_DEBUG, ("delif_output\n"));
+
+#ifdef DELIF_OUTPUT_DROPRATE
+ if(((double)rand()/(double)RAND_MAX) < DELIF_OUTPUT_DROPRATE) {
+ DEBUGF(DELIF_DEBUG, ("delif_output: Packet dropped\n"));
+ return 0;
+ }
+#endif /* DELIF_OUTPUT_DROPRATE */
+
+
+ DEBUGF(DELIF_DEBUG, ("delif_output\n"));
+
+
+ dp = malloc(sizeof(struct delif_pbuf));
+ data = malloc(p->tot_len);
+
+ i = 0;
+ for(q = p; q != NULL; q = q->next) {
+ for(j = 0; j < q->len; j++) {
+ data[i] = ((char *)q->payload)[j];
+ i++;
+ }
+ }
+
+
+ dp->p = pbuf_alloc(PBUF_LINK, 0, PBUF_ROM);
+ dp->p->payload = data;
+ dp->p->len = p->tot_len;
+ dp->p->tot_len = p->tot_len;
+ dp->ipaddr = ipaddr;
+ dp->time = sys_now() + DELIF_OUTPUT_DELAY;
+ dp->next = NULL;
+ if(output_list == NULL) {
+ output_list = dp;
+ } else {
+ for(np = output_list; np->next != NULL; np = np->next);
+ np->next = dp;
+ }
+
+
+ return ERR_OK;
+
+
+}
+/*-----------------------------------------------------------------------------------*/
+static err_t
+delif_input(struct pbuf *p, struct netif *inp)
+{
+ struct delif_pbuf *dp, *np;
+
+ DEBUGF(DELIF_DEBUG, ("delif_input\n"));
+#ifdef DELIF_INPUT_DROPRATE
+ if(((double)rand()/(double)RAND_MAX) < DELIF_INPUT_DROPRATE) {
+ DEBUGF(DELIF_DEBUG, ("delif_input: Packet dropped\n"));
+ pbuf_free(p);
+ return ERR_OK;
+ }
+#endif /* DELIF_INPUT_DROPRATE */
+
+
+ dp = malloc(sizeof(struct delif_pbuf));
+ dp->p = p;
+ dp->time = sys_now() + DELIF_INPUT_DELAY;
+ dp->next = NULL;
+ if(input_list == NULL) {
+ input_list = dp;
+ } else {
+ for(np = input_list; np->next != NULL; np = np->next);
+ np->next = dp;
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+delif_init(struct netif *netif)
+{
+ struct delif *del;
+
+ del = malloc(sizeof(struct delif));
+ netif->state = del;
+ netif->name[0] = 'd';
+ netif->name[1] = 'e';
+ netif->output = delif_output;
+
+ del->netif = malloc(sizeof(struct netif));
+#ifdef linux
+ /* tapif_init(del->netif);*/
+ tunif_init(del->netif);
+#else /* linux */
+ tunif_init(del->netif);
+#endif /* linux */
+ del->input = netif->input;
+ del->netif->input = delif_input;
+ sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif);
+ sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif);
+}
+
+/*-----------------------------------------------------------------------------------*/
+static void
+delif_thread(void *arg)
+{
+ struct netif *netif = arg;
+ struct delif *del;
+ sys_sem_t sem;
+
+ del = netif->state;
+#ifdef linux
+ tapif_init(del->netif);
+#else /* linux */
+ tunif_init(del->netif);
+#endif /* linux */
+
+ sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif);
+ sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif);
+
+ sem = sys_sem_new(0);
+ sys_sem_wait(sem);
+
+}
+/*-----------------------------------------------------------------------------------*/
+void
+delif_init_thread(struct netif *netif)
+{
+ struct delif *del;
+
+ DEBUGF(DELIF_DEBUG, ("delif_init_thread\n"));
+
+ del = malloc(sizeof(struct delif));
+ netif->state = del;
+ netif->name[0] = 'd';
+ netif->name[1] = 'e';
+ netif->output = delif_output;
+
+ del->netif = malloc(sizeof(struct netif));
+ del->netif->ip_addr = netif->ip_addr;
+ del->netif->gw = netif->gw;
+ del->netif->netmask = netif->netmask;
+ del->input = netif->input;
+ del->netif->input = delif_input;
+ sys_thread_new(delif_thread, netif);
+}
+
+/*-----------------------------------------------------------------------------------*/
+
+
+
diff --git a/src/arch/unix/netif/list.c b/src/arch/unix/netif/list.c
new file mode 100644
index 0000000..288cebc
--- /dev/null
+++ b/src/arch/unix/netif/list.c
@@ -0,0 +1,162 @@
+/*
+ * 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/list.h"
+
+#include <stdlib.h>
+
+struct list {
+ struct elem *first, *last;
+ int size, elems;
+};
+
+struct elem {
+ struct elem *next;
+ void *data;
+};
+
+/*-----------------------------------------------------------------------------------*/
+struct list *
+list_new(int size)
+{
+ struct list *list;
+ list = malloc(sizeof(struct list));
+ list->first = list->last = NULL;
+ list->size = size;
+ list->elems = 0;
+ return list;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+list_push(struct list *list, void *data)
+{
+ struct elem *elem;
+
+ if(list->elems < list->size) {
+ elem = malloc(sizeof(struct elem));
+ elem->data = data;
+ elem->next = NULL;
+ if(list->last != NULL) {
+ list->last->next = elem;
+ }
+ list->last = elem;
+ if(list->first == NULL) {
+ list->first = elem;
+ }
+ list->elems++;
+ return 1;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+list_pop(struct list *list)
+{
+ struct elem *elem;
+ void *data;
+
+ if(list->elems > 0) {
+ elem = list->first;
+ if(elem == list->last) {
+ list->last = elem->next;
+ }
+ list->first = elem->next;
+
+ list->elems--;
+
+ data = elem->data;
+ free(elem);
+
+ return data;
+ }
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+list_first(struct list *list)
+{
+ return list->first;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+list_elems(struct list *list)
+{
+ return list->elems;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+list_delete(struct list *list)
+{
+ while(list_pop(list) != NULL);
+ free(list);
+}
+/*-----------------------------------------------------------------------------------*/
+int
+list_remove(struct list *list, void *elem)
+{
+ struct elem *e, *p;
+
+ p = NULL;
+ for(e = list->first; e != NULL; e = e->next) {
+ if(e->data == elem) {
+ if(p != NULL) {
+ p->next = e->next;
+ } else {
+ list->first = e->next;
+ }
+ if(list->last == e) {
+ list->last = p;
+ if(p != NULL) {
+ p->next = NULL;
+ }
+ }
+ free(e);
+ list->elems--;
+ return 1;
+ }
+ p = e;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+list_map(struct list *list, void (* func)(void *arg))
+{
+ struct elem *e;
+
+ for(e = list->first; e != NULL; e = e->next) {
+ func(e->data);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+
diff --git a/src/arch/unix/netif/pcapif.c b/src/arch/unix/netif/pcapif.c
new file mode 100644
index 0000000..cfdccc1
--- /dev/null
+++ b/src/arch/unix/netif/pcapif.c
@@ -0,0 +1,214 @@
+/*
+ * 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 linux /* Apparently, this doesn't work under Linux. */
+
+#include "lwip/debug.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <pcap.h>
+
+#include "netif/etharp.h"
+
+#include "lwip/stats.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "netif/unixif.h"
+#include "lwip/sys.h"
+
+#include "lwip/ip.h"
+
+#include "lwip/list.h"
+
+#include "netif/tcpdump.h"
+
+struct pcapif {
+ pcap_t *pd;
+ sys_sem_t sem;
+ u8_t pkt[2048];
+ u32_t len;
+ u32_t lasttime;
+ struct pbuf *p;
+ struct eth_addr *ethaddr;
+};
+
+static char errbuf[PCAP_ERRBUF_SIZE];
+
+/*-----------------------------------------------------------------------------------*/
+static err_t
+pcapif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+timeout(void *arg)
+{
+ struct netif *netif;
+ struct pcapif *pcapif;
+ struct pbuf *p, *q;
+ u8_t *bufptr;
+ struct eth_hdr *ethhdr;
+
+ netif = (struct netif *)arg;
+ pcapif = netif->state;
+ ethhdr = (struct eth_hdr *)pcapif->pkt;
+
+
+ if(htons(ethhdr->type) != ETHTYPE_IP ||
+ ip_lookup(pcapif->pkt + 14, netif)) {
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_LINK, pcapif->len, PBUF_POOL);
+
+ if(p != NULL) {
+ /* We iterate over the pbuf chain until we have read the entire
+ packet into the pbuf. */
+ bufptr = (u_char *)pcapif->pkt;
+ 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;
+ }
+
+ ethhdr = p->payload;
+ switch(htons(ethhdr->type)) {
+ case ETHTYPE_IP:
+ arp_ip_input(netif, p);
+ pbuf_header(p, -14);
+ netif->input(p, netif);
+ break;
+ case ETHTYPE_ARP:
+ p = arp_arp_input(netif, pcapif->ethaddr, p);
+ if(p != NULL) {
+ printf("ARP outout\n");
+ pbuf_free(p);
+ }
+ break;
+ default:
+ pbuf_free(p);
+ break;
+ }
+ }
+ } else {
+ printf("ip_lookup dropped\n");
+ }
+
+ sys_sem_signal(pcapif->sem);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+callback(u_char *arg, const struct pcap_pkthdr *hdr, const u_char *pkt)
+{
+ struct netif *netif;
+ struct pcapif *pcapif;
+ u32_t time, lasttime;
+
+ netif = (struct netif *)arg;
+ pcapif = netif->state;
+
+ pcapif->len = hdr->len;
+
+ bcopy(pkt, pcapif->pkt, hdr->len);
+
+ time = hdr->ts.tv_sec * 1000 + hdr->ts.tv_usec / 1000;
+
+ lasttime = pcapif->lasttime;
+ pcapif->lasttime = time;
+
+
+ if(lasttime == 0) {
+ sys_timeout(1000, timeout, netif);
+ } else {
+ sys_timeout(time - lasttime, timeout, netif);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+pcapif_thread(void *arg)
+{
+ struct netif *netif;
+ struct pcapif *pcapif;
+ netif = arg;
+ pcapif = netif->state;
+
+ while(1) {
+ pcap_loop(pcapif->pd, 1, callback, (u_char *)netif);
+ sys_sem_wait(pcapif->sem);
+ if(pcapif->p != NULL) {
+ netif->input(pcapif->p, netif);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+pcapif_init(struct netif *netif)
+{
+ struct pcapif *p;
+
+ p = malloc(sizeof(struct pcapif));
+ netif->state = p;
+ netif->name[0] = 'p';
+ netif->name[1] = 'c';
+ netif->output = pcapif_output;
+
+ p->pd = pcap_open_offline("pcapdump", errbuf);
+ if(p->pd == NULL) {
+ printf("pcapif_init: failed %s\n", errbuf);
+ return;
+ }
+
+ p->sem = sys_sem_new(0);
+ p->p = NULL;
+ p->lasttime = 0;
+
+ sys_thread_new(pcapif_thread, netif);
+}
+/*-----------------------------------------------------------------------------------*/
+#endif /* linux */
diff --git a/src/arch/unix/netif/sioslipif.c b/src/arch/unix/netif/sioslipif.c
new file mode 100644
index 0000000..9659e37
--- /dev/null
+++ b/src/arch/unix/netif/sioslipif.c
@@ -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 "lwip/def.h"
+#include "netif/sioslipif.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+
+/* The maximum size that an incoming packet can have. */
+#define MAX_SIZE 1500
+
+#define SLIP_END 0300
+#define SLIP_ESC 0333
+#define SLIP_ESC_END 0334
+#define SLIP_ESC_ESC 0335
+
+/* Define those to whatever is needed to send and receive one byte of
+ data. */
+#define SIO_SEND(c)
+#define SIO_RECV(c)
+
+static const unsigned char slip_end = SLIP_END,
+ slip_esc = SLIP_ESC,
+ slip_esc_end = SLIP_ESC_END,
+ slip_esc_esc = SLIP_ESC_ESC;
+
+/*-----------------------------------------------------------------------------------*/
+static err_t
+sioslipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
+{
+ struct pbuf *q;
+ int i;
+ unsigned char *ptr;
+ u8_t c;
+ /* Send pbuf out on the serial I/O device. */
+ SIO_SEND(slip_end);
+
+ for(q = p; q != NULL; q = q->next) {
+ ptr = q->payload;
+ for(i = 0; i < q->len; i++) {
+ c = *ptr++;
+ switch(c) {
+ case SLIP_END:
+ SIO_SEND(slip_esc);
+ SIO_SEND(slip_esc_end);
+ break;
+ case SLIP_ESC:
+ SIO_SEND(slip_esc);
+ SIO_SEND(slip_esc_esc);
+ break;
+ default:
+ SIO_SEND(c);
+ break;
+ }
+ }
+ }
+#ifdef LINK_STATS
+ stats.link.xmit++;
+#endif /* LINK_STATS */
+ SIO_SEND(slip_end);
+
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static struct pbuf *
+sioslipif_input(void)
+{
+ u8_t c;
+ struct pbuf *p, *q;
+ int recved;
+ int i;
+
+ q = p = NULL;
+ recved = i = 0;
+ c = 0;
+
+ while(1) {
+ SIO_RECV(c);
+ switch(c) {
+ case SLIP_END:
+ if(p == NULL) {
+ return sioslipif_input();
+ }
+ if(recved > 0) {
+ /* Received whole packet. */
+ pbuf_realloc(q, recved);
+#ifdef LINK_STATS
+ stats.link.recv++;
+#endif /* LINK_STATS */
+ return q;
+ }
+ break;
+ case SLIP_ESC:
+ SIO_RECV(c);
+ switch(c) {
+ case SLIP_ESC_END:
+ c = SLIP_END;
+ break;
+ case SLIP_ESC_ESC:
+ c = SLIP_ESC;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if(p == NULL) {
+ p = pbuf_alloc(PBUF_LINK, 128, PBUF_POOL);
+#ifdef LINK_STATS
+ if(p == NULL) {
+ stats.link.drop++;
+ }
+#endif /* LINK_STATS */
+ if(q != NULL) {
+ pbuf_chain(q, p);
+ } else {
+ q = p;
+ }
+ }
+ if(p != NULL && recved < MAX_SIZE) {
+ ((u8_t *)p->payload)[i] = c;
+ recved++;
+ i++;
+ if(i >= p->len) {
+ i = 0;
+ p = NULL;
+ }
+ }
+ break;
+ }
+
+ }
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+sioslipif_loop(void *arg)
+{
+ struct pbuf *p;
+ struct netif *netif;
+
+ netif = arg;
+ while(1) {
+ p = sioslipif_input();
+ netif->input(p, netif);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sioslipif_init(struct netif *netif)
+{
+ netif->state = NULL;
+ netif->name[0] = 's';
+ netif->name[1] = 'l';
+ netif->output = sioslipif_output;
+
+ sys_thread_new((void *)sioslipif_loop, netif);
+ /* Do some magic to make it possible to receive data from the serial I/O device. */
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/unix/netif/tapif.c b/src/arch/unix/netif/tapif.c
new file mode 100644
index 0000000..ac9f1ea
--- /dev/null
+++ b/src/arch/unix/netif/tapif.c
@@ -0,0 +1,355 @@
+/*
+ * 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 <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+
+#include "lwip/debug.h"
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/ip.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include "netif/etharp.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 */
+
+#define IFNAME0 't'
+#define IFNAME1 'p'
+
+static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+
+struct tapif {
+ struct eth_addr *ethaddr;
+ /* Add whatever per-interface state that is needed here. */
+ int fd;
+};
+
+/* Forward declarations. */
+static void tapif_input(struct netif *netif);
+static err_t tapif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+static void tapif_thread(void *data);
+
+/*-----------------------------------------------------------------------------------*/
+static void
+low_level_init(struct netif *netif)
+{
+ struct tapif *tapif;
+ char buf[100];
+
+ tapif = netif->state;
+
+ /* Obtain MAC address from network interface. */
+
+ /* (We just fake an address...) */
+ tapif->ethaddr->addr[0] = 0x1;
+ tapif->ethaddr->addr[1] = 0x2;
+ tapif->ethaddr->addr[2] = 0x3;
+ tapif->ethaddr->addr[3] = 0x4;
+ tapif->ethaddr->addr[4] = 0x5;
+ tapif->ethaddr->addr[5] = 0x6;
+
+ /* Do whatever else is needed to initialize interface. */
+
+ tapif->fd = open(DEVTAP, O_RDWR);
+ DEBUGF(TAPIF_DEBUG, ("tapif_init: fd %d\n", tapif->fd));
+ if(tapif->fd == -1) {
+ perror("tapif_init");
+ exit(1);
+ }
+
+#ifdef linux
+ {
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
+ if (ioctl(tapif->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)));
+
+ DEBUGF(TAPIF_DEBUG, ("tapif_init: system(\"%s\");\n", buf));
+ system(buf);
+ sys_thread_new(tapif_thread, netif);
+
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * 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 pbuf *q;
+ char buf[1500];
+ char *bufptr;
+ struct tapif *tapif;
+
+ tapif = 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(tapif->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 tapif *tapif)
+{
+ 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(tapif->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(); */
+ }
+
+ return p;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+tapif_thread(void *arg)
+{
+ struct netif *netif;
+ struct tapif *tapif;
+ fd_set fdset;
+ int ret;
+
+ netif = arg;
+ tapif = netif->state;
+
+ while(1) {
+ FD_ZERO(&fdset);
+ FD_SET(tapif->fd, &fdset);
+
+ /* Wait for a packet to arrive. */
+ ret = select(tapif->fd + 1, &fdset, NULL, NULL, NULL);
+
+ if(ret == 1) {
+ /* Handle incoming packet. */
+ tapif_input(netif);
+ } else if(ret == -1) {
+ perror("tapif_thread: select");
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tapif_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
+tapif_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;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tapif_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
+tapif_input(struct netif *netif)
+{
+ struct tapif *tapif;
+ struct eth_hdr *ethhdr;
+ struct pbuf *p, *q;
+
+
+ tapif = netif->state;
+
+ p = low_level_input(tapif);
+
+ if(p == NULL) {
+ DEBUGF(TAPIF_DEBUG, ("tapif_input: low_level_input returned NULL\n"));
+ return;
+ }
+ ethhdr = p->payload;
+
+ q = NULL;
+ switch(htons(ethhdr->type)) {
+ case ETHTYPE_IP:
+ DEBUGF(TAPIF_DEBUG, ("tapif_input: IP packet\n"));
+ q = etharp_ip_input(netif, p);
+ pbuf_header(p, -14);
+ netif->input(p, netif);
+ break;
+ case ETHTYPE_ARP:
+ DEBUGF(TAPIF_DEBUG, ("tapif_input: ARP packet\n"));
+ q = etharp_arp_input(netif, tapif->ethaddr, p);
+ break;
+ default:
+ pbuf_free(p);
+ break;
+ }
+ if(q != NULL) {
+ low_level_output(netif, q);
+ pbuf_free(q);
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+arp_timer(void *arg)
+{
+ etharp_tmr();
+ sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tapif_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
+tapif_init(struct netif *netif)
+{
+ struct tapif *tapif;
+
+ tapif = mem_malloc(sizeof(struct tapif));
+ netif->state = tapif;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = tapif_output;
+ netif->linkoutput = low_level_output;
+
+ tapif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
+
+ low_level_init(netif);
+ etharp_init();
+
+ sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/unix/netif/tunif.c b/src/arch/unix/netif/tunif.c
new file mode 100644
index 0000000..7e376dc
--- /dev/null
+++ b/src/arch/unix/netif/tunif.c
@@ -0,0 +1,298 @@
+/*
+ * 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 <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+
+#include "lwip/debug.h"
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/ip.h"
+#include "lwip/mem.h"
+#include "lwip/netif.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+
+#define IFNAME0 't'
+#define IFNAME1 'n'
+
+struct tunif {
+ /* Add whatever per-interface state that is needed here. */
+ int fd;
+};
+
+/* Forward declarations. */
+static void tunif_input(struct netif *netif);
+static err_t tunif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+static void tunif_thread(void *data);
+
+/*-----------------------------------------------------------------------------------*/
+static void
+low_level_init(struct netif *netif)
+{
+ struct tunif *tunif;
+ char buf[100];
+
+ tunif = netif->state;
+
+ /* Obtain MAC address from network interface. */
+
+ /* Do whatever else is needed to initialize interface. */
+
+ tunif->fd = open("/dev/tun0", O_RDWR);
+ DEBUGF(TUNIF_DEBUG, ("tunif_init: fd %d\n", tunif->fd));
+ if(tunif->fd == -1) {
+ perror("tunif_init");
+ exit(1);
+ }
+ snprintf(buf, sizeof(buf), "ifconfig tun0 inet %d.%d.%d.%d %d.%d.%d.%d",
+ ip4_addr1(&(netif->gw)),
+ ip4_addr2(&(netif->gw)),
+ ip4_addr3(&(netif->gw)),
+ ip4_addr4(&(netif->gw)),
+ ip4_addr1(&(netif->ip_addr)),
+ ip4_addr2(&(netif->ip_addr)),
+ ip4_addr3(&(netif->ip_addr)),
+ ip4_addr4(&(netif->ip_addr)));
+
+ DEBUGF(TUNIF_DEBUG, ("tunif_init: system(\"%s\");\n", buf));
+ system(buf);
+ sys_thread_new(tunif_thread, netif);
+
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * 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 tunif *tunif, struct pbuf *p)
+{
+ struct pbuf *q;
+ char buf[1500];
+ char *bufptr;
+
+ /* initiate transfer(); */
+
+ if(((double)rand()/(double)RAND_MAX) < 0.4) {
+ printf("drop\n");
+ return ERR_OK;
+ }
+
+
+ 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(tunif->fd, buf, p->tot_len) == -1) {
+ perror("tunif: 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 tunif *tunif)
+{
+ 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(tunif->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(); */
+ }
+
+ return p;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+tunif_thread(void *arg)
+{
+ struct netif *netif;
+ struct tunif *tunif;
+ fd_set fdset;
+ int ret;
+
+ netif = arg;
+ tunif = netif->state;
+
+ while(1) {
+ FD_ZERO(&fdset);
+ FD_SET(tunif->fd, &fdset);
+
+ /* Wait for a packet to arrive. */
+ ret = select(tunif->fd + 1, &fdset, NULL, NULL, NULL);
+
+ if(ret == 1) {
+ /* Handle incoming packet. */
+ tunif_input(netif);
+ } else if(ret == -1) {
+ perror("tunif_thread: select");
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tunif_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
+tunif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+ struct tunif *tunif;
+
+ tunif = netif->state;
+
+ return low_level_output(tunif, p);
+
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tunif_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
+tunif_input(struct netif *netif)
+{
+ struct tunif *tunif;
+ struct pbuf *p;
+
+
+ tunif = netif->state;
+
+ p = low_level_input(tunif);
+
+ if(p == NULL) {
+ DEBUGF(TUNIF_DEBUG, ("tunif_input: low_level_input returned NULL\n"));
+ return;
+ }
+
+ if(ip_lookup(p->payload, netif)) {
+ netif->input(p, netif);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tunif_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
+tunif_init(struct netif *netif)
+{
+ struct tunif *tunif;
+
+ tunif = mem_malloc(sizeof(struct tunif));
+ netif->state = tunif;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = tunif_output;
+
+
+ low_level_init(netif);
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/arch/unix/netif/unixif.c b/src/arch/unix/netif/unixif.c
new file mode 100644
index 0000000..43ea14a
--- /dev/null
+++ b/src/arch/unix/netif/unixif.c
@@ -0,0 +1,480 @@
+/*
+ * 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 <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#include "lwip/stats.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "netif/unixif.h"
+#include "lwip/sys.h"
+
+#include "lwip/list.h"
+
+#include "netif/tcpdump.h"
+
+#define UNIXIF_BPS 512000
+#define UNIXIF_QUEUELEN 6
+/*#define UNIXIF_DROP_FIRST */
+
+struct unixif_buf {
+ struct pbuf *p;
+ unsigned short len, tot_len;
+ void *payload;
+};
+
+struct unixif {
+ int fd;
+ sys_sem_t sem;
+ struct list *q;
+};
+
+
+/*-----------------------------------------------------------------------------------*/
+static int
+unix_socket_client(char *name)
+{
+ int fd, len;
+ struct sockaddr_un unix_addr;
+
+ /* create a Unix domain stream socket */
+ if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("unixif: unix_socket_client: socket");
+ return(-1);
+ }
+
+ /* fill socket address structure w/our address */
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ sprintf(unix_addr.sun_path, "%s%05d", "/var/tmp/", getpid());
+#ifndef linux
+ len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) +
+ strlen(unix_addr.sun_path) + 1;
+ unix_addr.sun_len = len;
+#else
+ len = sizeof(unix_addr.sun_family) +
+ strlen(unix_addr.sun_path) + 1;
+#endif /* linux */
+
+ unlink(unix_addr.sun_path); /* in case it already exists */
+ if(bind(fd, (struct sockaddr *) &unix_addr,
+ sizeof(struct sockaddr_un)) < 0) {
+ perror("unixif: unix_socket_client: socket");
+ return(-1);
+ }
+ if(chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) {
+ perror("unixif: unix_socket_client: socket");
+ return(-1);
+ }
+
+ /* fill socket address structure w/server's addr */
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strcpy(unix_addr.sun_path, name);
+#ifndef linux
+ len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) +
+ strlen(unix_addr.sun_path) + 1;
+ unix_addr.sun_len = len;
+#else
+ len = sizeof(unix_addr.sun_family) + strlen(unix_addr.sun_path) + 1;
+#endif /* linux */
+ if(connect(fd, (struct sockaddr *) &unix_addr,
+ sizeof(struct sockaddr_un)) < 0) {
+ perror("unixif: unix_socket_client: socket");
+ return(-1);
+ }
+ return(fd);
+}
+
+/*-----------------------------------------------------------------------------------*/
+static int
+unix_socket_server(char *name)
+{
+ int fd, len;
+ struct sockaddr_un unix_addr;
+
+ /* create a Unix domain stream socket */
+ if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("unixif: unix_socket_server: socket");
+ return(-1);
+ }
+
+ unlink(name); /* in case it already exists */
+
+ /* fill in socket address structure */
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strcpy(unix_addr.sun_path, name);
+#ifndef linux
+ len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) +
+ strlen(unix_addr.sun_path) + 1;
+ unix_addr.sun_len = len;
+#else
+ len = sizeof(unix_addr.sun_family) +
+ strlen(unix_addr.sun_path) + 1;
+#endif /* linux */
+
+ /* bind the name to the descriptor */
+ if(bind(fd, (struct sockaddr *) &unix_addr,
+ sizeof(struct sockaddr_un)) < 0) {
+ perror("unixif: unix_socket_server: bind");
+ return(-1);
+ }
+
+ if(chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) {
+ perror("unixif: unix_socket_server: chmod");
+ return(-1);
+ }
+
+
+ if(listen(fd, 5) < 0) { /* tell kernel we're a server */
+ perror("unixif: unix_socket_server: listen");
+ return(-1);
+ }
+
+ return(fd);
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+unixif_input_handler(void *data)
+{
+ struct netif *netif;
+ struct unixif *unixif;
+ char buf[4096], *bufptr;
+ int len, plen, rlen;
+ struct pbuf *p, *q;
+
+ netif = data;
+ unixif = netif->state;
+
+ len = read(unixif->fd, &plen, sizeof(int));
+ if(len == -1) {
+ perror("unixif_irq_handler: read");
+ abort();
+ }
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: len == %d plen == %d bytes\n", len, plen));
+ if(len == sizeof(int)) {
+
+ if(plen < 20 || plen > 1500) {
+ DEBUGF(UNIXIF_DEBUG, ("plen %d!\n", plen));
+ return;
+ }
+
+ len = read(unixif->fd, buf, plen);
+ if(len == -1) {
+ perror("unixif_irq_handler: read");
+ abort();
+ }
+ DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: read %d bytes\n", len));
+ p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
+
+ if(p != NULL) {
+ rlen = len;
+ bufptr = buf;
+ q = p;
+ while(rlen > 0) {
+ bcopy(bufptr, q->payload, rlen > q->len? q->len: rlen);
+ rlen -= q->len;
+ bufptr += q->len;
+ q = q->next;
+ }
+ pbuf_realloc(p, len);
+#ifdef LINK_STATS
+ stats.link.recv++;
+#endif /* LINK_STATS */
+ tcpdump(p);
+ netif->input(p, netif);
+ } else {
+ DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: could not allocate pbuf\n"));
+ }
+
+
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+unixif_thread(void *arg)
+{
+ struct netif *netif;
+ struct unixif *unixif;
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_thread: started.\n"));
+
+ netif = arg;
+ unixif = netif->state;
+
+
+ while(1) {
+ sys_sem_wait(unixif->sem);
+ unixif_input_handler(netif);
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+unixif_thread2(void *arg)
+{
+ struct netif *netif;
+ struct unixif *unixif;
+ fd_set fdset;
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_thread2: started.\n"));
+
+ netif = arg;
+ unixif = netif->state;
+
+ while(1) {
+ FD_ZERO(&fdset);
+ FD_SET(unixif->fd, &fdset);
+
+ if(select(unixif->fd + 1, &fdset, NULL, NULL, NULL) > 0) {
+ sys_sem_signal(unixif->sem);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void unixif_output_timeout(void *arg);
+
+static err_t
+unixif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
+{
+ struct unixif *unixif;
+ struct unixif_buf *buf;
+ unixif = netif->state;
+
+ buf = malloc(sizeof(struct unixif_buf));
+ buf->p = p;
+ buf->len = p->len;
+ buf->tot_len = p->tot_len;
+ buf->payload = p->payload;
+
+ if(list_elems(unixif->q) == 0) {
+ pbuf_ref(p);
+ list_push(unixif->q, buf);
+ sys_timeout((double)p->tot_len * 8000.0 / UNIXIF_BPS, unixif_output_timeout,
+ netif);
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_output: first on list\n"));
+
+ } else {
+ pbuf_ref(p);
+ if(list_push(unixif->q, buf) == 0) {
+#ifdef UNIXIF_DROP_FIRST
+ struct unixif_buf *buf2;
+
+ buf2 = list_pop(unixif->q);
+ pbuf_free(buf2->p);
+ free(buf2);
+ list_push(unixif->q, buf);
+#else
+ free(buf);
+ pbuf_free(p);
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_output: drop\n"));
+
+#endif /* UNIXIF_DROP_FIRST */
+#ifdef LINK_STATS
+ stats.link.drop++;
+#endif /* LINK_STATS */
+
+ } else {
+ DEBUGF(UNIXIF_DEBUG, ("unixif_output: on list\n"));
+ }
+
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+unixif_output_timeout(void *arg)
+{
+ struct pbuf *p, *q;
+ int i, j, len;
+ unsigned short plen, ptot_len;
+ struct unixif_buf *buf;
+ void *payload;
+ struct netif *netif;
+ struct unixif *unixif;
+ char *data;
+
+ netif = arg;
+ unixif = netif->state;
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_output_timeout\n"));
+
+ /* buf = unixif->q[0];
+ unixif->q[0] = unixif->q[1];
+ unixif->q[1] = NULL;*/
+ buf = list_pop(unixif->q);
+
+ p = buf->p;
+
+ plen = p->len;
+ ptot_len = p->tot_len;
+ payload = p->payload;
+
+ p->len = buf->len;
+ p->tot_len = buf->tot_len;
+ p->payload = buf->payload;
+
+
+ if(p->tot_len == 0) {
+
+ DEBUGF(UNIXIF_DEBUG, ("p->len!\n"));
+ abort();
+ }
+ data = malloc(p->tot_len);
+
+ i = 0;
+ for(q = p; q != NULL; q = q->next) {
+ for(j = 0; j < q->len; j++) {
+ data[i] = ((char *)q->payload)[j];
+ i++;
+ }
+ }
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_output: sending %d (%d) bytes\n",
+ p->len, p->tot_len));
+
+ len = p->tot_len;
+ if(write(unixif->fd, &len, sizeof(int)) == -1) {
+ perror("unixif_output: write");
+ abort();
+ }
+
+ if(write(unixif->fd, data, p->tot_len) == -1) {
+ perror("unixif_output: write");
+ abort();
+ }
+ tcpdump(p);
+#ifdef LINK_STATS
+ stats.link.xmit++;
+#endif /* LINK_STATS */
+
+ free(data);
+ free(buf);
+ p->len = plen;
+ p->tot_len = ptot_len;
+ p->payload = payload;
+
+ pbuf_free(p);
+
+ /* if(unixif->q[0] != NULL) {
+ sys_timeout(unixif->q[0]->tot_len * 8000 / UNIXIF_BPS,
+ unixif_output_timeout, netif);
+ }*/
+ if(list_elems(unixif->q) > 0) {
+ sys_timeout(((struct unixif_buf *)list_first(unixif->q))->tot_len *
+ 8000.0 / UNIXIF_BPS,
+ unixif_output_timeout, netif);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+unixif_init_server(struct netif *netif)
+{
+ int fd, fd2;
+ struct sockaddr_un addr;
+ socklen_t len;
+ struct unixif *unixif;
+
+ fd = unix_socket_server("/tmp/unixif");
+
+ if(fd == -1) {
+ perror("unixif_server");
+ abort();
+ }
+ DEBUGF(UNIXIF_DEBUG, ("unixif_server: fd %d\n", fd));
+
+ unixif = malloc(sizeof(struct unixif));
+ netif->state = unixif;
+ netif->name[0] = 'u';
+ netif->name[1] = 'n';
+ netif->output = unixif_output;
+ unixif->q = list_new(UNIXIF_QUEUELEN);
+
+ printf("Now run ./simnode.\n");
+ len = sizeof(addr);
+ fd2 = accept(fd, (struct sockaddr *)&addr, &len);
+
+ if(fd2 == -1) {
+ perror("unixif_accept");
+ abort();
+ }
+
+ DEBUGF(UNIXIF_DEBUG, ("unixif_accept: %d\n", fd2));
+
+ unixif->fd = fd2;
+ unixif->sem = sys_sem_new(0);
+ sys_thread_new(unixif_thread, netif);
+ sys_thread_new(unixif_thread2, netif);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+unixif_init_client(struct netif *netif)
+{
+ struct unixif *unixif;
+ unixif = malloc(sizeof(struct unixif));
+ netif->state = unixif;
+ netif->name[0] = 'u';
+ netif->name[1] = 'n';
+ netif->output = unixif_output;
+
+ unixif->fd = unix_socket_client("/tmp/unixif");
+ if(unixif->fd == -1) {
+ perror("unixif_init");
+ abort();
+ }
+ unixif->q = list_new(UNIXIF_QUEUELEN);
+ unixif->sem = sys_sem_new(0);
+ sys_thread_new(unixif_thread, netif);
+ sys_thread_new(unixif_thread2, netif);
+}
+/*-----------------------------------------------------------------------------------*/
+
+
diff --git a/src/arch/unix/perf.c b/src/arch/unix/perf.c
new file mode 100644
index 0000000..009344a
--- /dev/null
+++ b/src/arch/unix/perf.c
@@ -0,0 +1,64 @@
+/*
+ * 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 "arch/perf.h"
+
+#include <stdio.h>
+
+static FILE *f;
+
+void
+perf_print(unsigned long c1l, unsigned long c1h,
+ unsigned long c2l, unsigned long c2h,
+ char *key)
+{
+ unsigned long long start, end;
+
+ start = (unsigned long long)c2h << 32 | c2l;
+ end = (unsigned long long)c1h << 32 | c1l;
+ fprintf(f, "%s: %llu\n", key, start - end);
+ fflush(NULL);
+}
+
+void
+perf_print_times(struct tms *start, struct tms *end, char *key)
+{
+ fprintf(f, "%s: %lu\n", key, end->tms_stime - start->tms_stime);
+ fflush(NULL);
+}
+
+void
+perf_init(char *fname)
+{
+ f = fopen(fname, "w");
+}
+
diff --git a/src/arch/unix/sys_arch.c b/src/arch/unix/sys_arch.c
new file mode 100644
index 0000000..b6af5ab
--- /dev/null
+++ b/src/arch/unix/sys_arch.c
@@ -0,0 +1,453 @@
+/*
+ * 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>
+ *
+ */
+
+/*
+ * Wed Apr 17 16:05:29 EDT 2002 (James Roth)
+ *
+ * - Fixed an unlikely sys_thread_new() race condition.
+ *
+ * - Made current_thread() work with threads which where
+ * not created with sys_thread_new(). This includes
+ * the main thread and threads made with pthread_create().
+ *
+ * - Catch overflows where more than SYS_MBOX_SIZE messages
+ * are waiting to be read. The sys_mbox_post() routine
+ * will block until there is more room instead of just
+ * leaking messages.
+ */
+#include "lwip/debug.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "lwip/sys.h"
+#include "lwip/opt.h"
+#include "lwip/stats.h"
+
+#define UMAX(a, b) ((a) > (b) ? (a) : (b))
+
+static struct sys_thread *threads = NULL;
+static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct sys_mbox_msg {
+ struct sys_mbox_msg *next;
+ void *msg;
+};
+
+#define SYS_MBOX_SIZE 128
+
+struct sys_mbox {
+ int first, last;
+ void *msgs[SYS_MBOX_SIZE];
+ struct sys_sem *mail;
+ struct sys_sem *mutex;
+ int wait_send;
+};
+
+struct sys_sem {
+ unsigned int c;
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+};
+
+struct sys_thread {
+ struct sys_thread *next;
+ struct sys_timeouts timeouts;
+ pthread_t pthread;
+};
+
+
+static struct timeval starttime;
+
+static struct sys_sem *sys_sem_new_(u8_t count);
+static void sys_sem_free_(struct sys_sem *sem);
+
+static u16_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ u16_t timeout);
+
+/*-----------------------------------------------------------------------------------*/
+static struct sys_thread *
+introduce_thread(pthread_t id)
+{
+ struct sys_thread *thread;
+
+ thread = malloc(sizeof(struct sys_thread));
+
+ if(thread) {
+ pthread_mutex_lock(&threads_mutex);
+ thread->next = threads;
+ thread->timeouts.next = NULL;
+ thread->pthread = id;
+ threads = thread;
+ pthread_mutex_unlock(&threads_mutex);
+ }
+
+ return thread;
+}
+/*-----------------------------------------------------------------------------------*/
+static struct sys_thread *
+current_thread(void)
+{
+ struct sys_thread *st;
+ pthread_t pt;
+ pt = pthread_self();
+ pthread_mutex_lock(&threads_mutex);
+
+ for(st = threads; st != NULL; st = st->next) {
+ if(pthread_equal(st->pthread, pt)) {
+ pthread_mutex_unlock(&threads_mutex);
+
+ return st;
+ }
+ }
+
+ pthread_mutex_unlock(&threads_mutex);
+
+ st = introduce_thread(pt);
+
+ if(!st) {
+ printf("current_thread???\n");
+ abort();
+ }
+
+ return st;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_thread_new(void (*function)(void *arg), void *arg)
+{
+ int code;
+ pthread_t tmp;
+ struct sys_thread *st = NULL;
+
+ code = pthread_create(&tmp,
+ NULL,
+ (void *(*)(void *))
+ function,
+ arg);
+
+ if(0 == code) {
+ st = introduce_thread(tmp);
+ }
+
+ if(NULL == st) {
+ DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x",
+ code, (int)st));
+ abort();
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_mbox *
+sys_mbox_new()
+{
+ struct sys_mbox *mbox;
+
+ mbox = malloc(sizeof(struct sys_mbox));
+ mbox->first = mbox->last = 0;
+ mbox->mail = sys_sem_new_(0);
+ mbox->mutex = sys_sem_new_(1);
+ mbox->wait_send = 0;
+
+#ifdef SYS_STATS
+ stats.sys.mbox.used++;
+ if(stats.sys.mbox.used > stats.sys.mbox.max) {
+ stats.sys.mbox.max = stats.sys.mbox.used;
+ }
+#endif /* SYS_STATS */
+
+ return mbox;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_free(struct sys_mbox *mbox)
+{
+ if(mbox != SYS_MBOX_NULL) {
+#ifdef SYS_STATS
+ stats.sys.mbox.used--;
+#endif /* SYS_STATS */
+ sys_sem_wait(mbox->mutex);
+
+ sys_sem_free_(mbox->mail);
+ sys_sem_free_(mbox->mutex);
+ mbox->mail = mbox->mutex = NULL;
+ /* DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
+ free(mbox);
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_post(struct sys_mbox *mbox, void *msg)
+{
+ u8_t first;
+
+ sys_sem_wait(mbox->mutex);
+
+ DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", mbox, msg));
+
+ while((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
+ mbox->wait_send++;
+ sys_sem_signal(mbox->mutex);
+ sys_arch_sem_wait(mbox->mail, 0);
+ sys_arch_sem_wait(mbox->mutex, 0);
+ mbox->wait_send--;
+ }
+
+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
+
+ if(mbox->last == mbox->first) {
+ first = 1;
+ } else {
+ first = 0;
+ }
+
+ mbox->last++;
+
+ if(first) {
+ sys_sem_signal(mbox->mail);
+ }
+
+ sys_sem_signal(mbox->mutex);
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u16_t timeout)
+{
+ u16_t time = 1;
+
+ /* The mutex lock is quick so we don't bother with the timeout
+ stuff here. */
+ sys_arch_sem_wait(mbox->mutex, 0);
+
+ while(mbox->first == mbox->last) {
+ sys_sem_signal(mbox->mutex);
+
+ /* We block while waiting for a mail to arrive in the mailbox. We
+ must be prepared to timeout. */
+ if(timeout != 0) {
+ time = sys_arch_sem_wait(mbox->mail, timeout);
+
+ /* If time == 0, the sem_wait timed out, and we return 0. */
+ if(time == 0) {
+ return 0;
+ }
+ } else {
+ sys_arch_sem_wait(mbox->mail, 0);
+ }
+
+ sys_arch_sem_wait(mbox->mutex, 0);
+ }
+
+ DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", mbox, *msg));
+
+ if(msg != NULL) {
+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
+ }
+
+ mbox->first++;
+
+ if(mbox->wait_send) {
+ sys_sem_signal(mbox->mail);
+ }
+
+ sys_sem_signal(mbox->mutex);
+
+ return time;
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_sem *
+sys_sem_new(u8_t count)
+{
+#ifdef SYS_STATS
+ stats.sys.sem.used++;
+ if(stats.sys.sem.used > stats.sys.sem.max) {
+ stats.sys.sem.max = stats.sys.sem.used;
+ }
+#endif /* SYS_STATS */
+ return sys_sem_new_(count);
+}
+
+/*-----------------------------------------------------------------------------------*/
+static struct sys_sem *
+sys_sem_new_(u8_t count)
+{
+ struct sys_sem *sem;
+
+ sem = malloc(sizeof(struct sys_sem));
+ sem->c = count;
+
+ pthread_cond_init(&(sem->cond), NULL);
+ pthread_mutex_init(&(sem->mutex), NULL);
+
+ return sem;
+}
+
+/*-----------------------------------------------------------------------------------*/
+static u16_t
+cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u16_t timeout)
+{
+ int tdiff;
+ unsigned long sec, usec;
+ struct timeval rtime1, rtime2;
+ struct timespec ts;
+ struct timezone tz;
+ int retval;
+
+ if(timeout > 0) {
+ /* Get a timestamp and add the timeout value. */
+ gettimeofday(&rtime1, &tz);
+ sec = rtime1.tv_sec;
+ usec = rtime1.tv_usec;
+ usec += timeout % 1000 * 1000;
+ sec += (int)(timeout / 1000) + (int)(usec / 1000000);
+ usec = usec % 1000000;
+ ts.tv_nsec = usec * 1000;
+ ts.tv_sec = sec;
+
+ retval = pthread_cond_timedwait(cond, mutex, &ts);
+
+ if(retval == ETIMEDOUT) {
+ return 0;
+ } else {
+ /* Calculate for how long we waited for the cond. */
+ gettimeofday(&rtime2, &tz);
+ tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
+ (rtime2.tv_usec - rtime1.tv_usec) / 1000;
+
+ if(tdiff <= 0) {
+ return 1;
+ }
+
+ return tdiff;
+ }
+ } else {
+ pthread_cond_wait(cond, mutex);
+ return 0;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+sys_arch_sem_wait(struct sys_sem *sem, u16_t timeout)
+{
+ u16_t time = 1;
+
+ pthread_mutex_lock(&(sem->mutex));
+ while(sem->c <= 0) {
+ if(timeout > 0) {
+ time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
+
+ if(time == 0) {
+ pthread_mutex_unlock(&(sem->mutex));
+ return 0;
+ }
+ /* pthread_mutex_unlock(&(sem->mutex));
+ return time; */
+ } else {
+ cond_wait(&(sem->cond), &(sem->mutex), 0);
+ }
+ }
+ sem->c--;
+ pthread_mutex_unlock(&(sem->mutex));
+ return time;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_signal(struct sys_sem *sem)
+{
+ pthread_mutex_lock(&(sem->mutex));
+ sem->c++;
+
+ if(sem->c > 1) {
+ sem->c = 1;
+ }
+
+ pthread_cond_broadcast(&(sem->cond));
+ pthread_mutex_unlock(&(sem->mutex));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_free(struct sys_sem *sem)
+{
+ if(sem != SYS_SEM_NULL) {
+#ifdef SYS_STATS
+ stats.sys.sem.used--;
+#endif /* SYS_STATS */
+ sys_sem_free_(sem);
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+static void
+sys_sem_free_(struct sys_sem *sem)
+{
+ pthread_cond_destroy(&(sem->cond));
+ pthread_mutex_destroy(&(sem->mutex));
+ free(sem);
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned long
+sys_unix_now()
+{
+ struct timeval tv;
+ struct timezone tz;
+ long sec, usec;
+ unsigned long msec;
+ gettimeofday(&tv, &tz);
+
+ sec = tv.tv_sec - starttime.tv_sec;
+ usec = tv.tv_usec - starttime.tv_usec;
+ msec = sec * 1000 + usec / 1000;
+
+ return msec;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_init()
+{
+ struct timezone tz;
+ gettimeofday(&starttime, &tz);
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_timeouts *
+sys_arch_timeouts(void)
+{
+ struct sys_thread *thread;
+
+ thread = current_thread();
+ return &thread->timeouts;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/inet.c b/src/core/inet.c
new file mode 100644
index 0000000..c8d7a85
--- /dev/null
+++ b/src/core/inet.c
@@ -0,0 +1,162 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* inet.c
+ *
+ * Functions common to all TCP/IP modules, such as the Internet checksum and the
+ * byte order functions.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/arch.h"
+
+#include "lwip/def.h"
+#include "lwip/inet.h"
+
+
+/*-----------------------------------------------------------------------------------*/
+static u16_t
+lwip_chksum(void *dataptr, int len)
+{
+ u32_t acc;
+
+ for(acc = 0; len > 1; len -= 2) {
+ acc += *((u16_t *)dataptr)++;
+ }
+
+ /* add up any odd byte */
+ if(len == 1) {
+ acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
+ DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", *(u8_t *)dataptr));
+ }
+ acc = (acc >> 16) + (acc & 0xffffUL);
+
+ if(acc & 0xffff0000 != 0) {
+ acc = (acc >> 16) + (acc & 0xffffUL);
+ }
+
+ return (u16_t)acc;
+}
+/*-----------------------------------------------------------------------------------*/
+/* inet_chksum_pseudo:
+ *
+ * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ */
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum_pseudo(struct pbuf *p,
+ struct ip_addr *src, struct ip_addr *dest,
+ u8_t proto, u16_t proto_len)
+{
+ u32_t acc;
+ struct pbuf *q;
+ u8_t swapped;
+
+ acc = 0;
+ swapped = 0;
+ for(q = p; q != NULL; q = q->next) {
+ acc += lwip_chksum(q->payload, q->len);
+ while(acc >> 16) {
+ acc = (acc & 0xffffUL) + (acc >> 16);
+ }
+ if(q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+ }
+ }
+
+ if(swapped) {
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+ }
+ acc += (src->addr & 0xffffUL);
+ acc += ((src->addr >> 16) & 0xffffUL);
+ acc += (dest->addr & 0xffffUL);
+ acc += ((dest->addr >> 16) & 0xffffUL);
+ acc += (u32_t)htons((u16_t)proto);
+ acc += (u32_t)htons(proto_len);
+
+ while(acc >> 16) {
+ acc = (acc & 0xffffUL) + (acc >> 16);
+ }
+ return ~(acc & 0xffffUL);
+}
+/*-----------------------------------------------------------------------------------*/
+/* inet_chksum:
+ *
+ * Calculates the Internet checksum over a portion of memory. Used primarely for IP
+ * and ICMP.
+ */
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum(void *dataptr, u16_t len)
+{
+ u32_t acc;
+
+ acc = lwip_chksum(dataptr, len);
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ return ~(acc & 0xffff);
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum_pbuf(struct pbuf *p)
+{
+ u32_t acc;
+ struct pbuf *q;
+ u8_t swapped;
+
+ acc = 0;
+ swapped = 0;
+ for(q = p; q != NULL; q = q->next) {
+ acc += lwip_chksum(q->payload, q->len);
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ if(q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
+ }
+ }
+
+ if(swapped) {
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
+ }
+ return ~(acc & 0xffff);
+}
+
+
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/inet6.c b/src/core/inet6.c
new file mode 100644
index 0000000..028f067
--- /dev/null
+++ b/src/core/inet6.c
@@ -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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* inet6.c
+ *
+ * Functions common to all TCP/IP modules, such as the Internet checksum and the
+ * byte order functions.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/inet.h"
+
+
+/*-----------------------------------------------------------------------------------*/
+/* chksum:
+ *
+ * Sums up all 16 bit words in a memory portion. Also includes any odd byte.
+ * This function is used by the other checksum functions.
+ *
+ * For now, this is not optimized. Must be optimized for the particular processor
+ * arcitecture on which it is to run. Preferebly coded in assembler.
+ */
+/*-----------------------------------------------------------------------------------*/
+static u32_t
+chksum(void *dataptr, u16_t len)
+{
+ u16_t *sdataptr = dataptr;
+ u32_t acc;
+
+
+ for(acc = 0; len > 1; len -= 2) {
+ acc += *sdataptr++;
+ }
+
+ /* add up any odd byte */
+ if(len == 1) {
+ acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
+ }
+
+ return acc;
+
+}
+/*-----------------------------------------------------------------------------------*/
+/* inet_chksum_pseudo:
+ *
+ * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ */
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum_pseudo(struct pbuf *p,
+ struct ip_addr *src, struct ip_addr *dest,
+ u8_t proto, u32_t proto_len)
+{
+ u32_t acc;
+ struct pbuf *q;
+ u8_t swapped, i;
+
+ acc = 0;
+ swapped = 0;
+ for(q = p; q != NULL; q = q->next) {
+ acc += chksum(q->payload, q->len);
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ if(q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
+ }
+ }
+
+ if(swapped) {
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
+ }
+
+ for(i = 0; i < 8; i++) {
+ acc += ((u16_t *)src->addr)[i] & 0xffff;
+ acc += ((u16_t *)dest->addr)[i] & 0xffff;
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ }
+ acc += (u16_t)htons((u16_t)proto);
+ acc += ((u16_t *)&proto_len)[0] & 0xffff;
+ acc += ((u16_t *)&proto_len)[1] & 0xffff;
+
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ return ~(acc & 0xffff);
+}
+/*-----------------------------------------------------------------------------------*/
+/* inet_chksum:
+ *
+ * Calculates the Internet checksum over a portion of memory. Used primarely for IP
+ * and ICMP.
+ */
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum(void *dataptr, u16_t len)
+{
+ u32_t acc, sum;
+
+ acc = chksum(dataptr, len);
+ sum = (acc & 0xffff) + (acc >> 16);
+ sum += (sum >> 16);
+ return ~(sum & 0xffff);
+}
+/*-----------------------------------------------------------------------------------*/
+u16_t
+inet_chksum_pbuf(struct pbuf *p)
+{
+ u32_t acc;
+ struct pbuf *q;
+ u8_t swapped;
+
+ acc = 0;
+ swapped = 0;
+ for(q = p; q != NULL; q = q->next) {
+ acc += chksum(q->payload, q->len);
+ while(acc >> 16) {
+ acc = (acc & 0xffff) + (acc >> 16);
+ }
+ if(q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
+ }
+ }
+
+ if(swapped) {
+ acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
+ }
+ return ~(acc & 0xffff);
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/ipv4/icmp.c b/src/core/ipv4/icmp.c
new file mode 100644
index 0000000..1ba58fc
--- /dev/null
+++ b/src/core/ipv4/icmp.c
@@ -0,0 +1,199 @@
+/*
+ * 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>
+ *
+ */
+
+/* Some ICMP messages should be passed to the transport protocols. This
+ is not implemented. */
+
+#include "lwip/debug.h"
+
+#include "lwip/icmp.h"
+#include "lwip/inet.h"
+#include "lwip/ip.h"
+#include "lwip/def.h"
+
+#include "lwip/stats.h"
+
+/*-----------------------------------------------------------------------------------*/
+void
+icmp_input(struct pbuf *p, struct netif *inp)
+{
+ unsigned char type;
+ struct icmp_echo_hdr *iecho;
+ struct ip_hdr *iphdr;
+ struct ip_addr tmpaddr;
+ u16_t hlen;
+
+#ifdef ICMP_STATS
+ ++stats.icmp.recv;
+#endif /* ICMP_STATS */
+
+
+ iphdr = p->payload;
+ hlen = IPH_HL(iphdr) * 4/sizeof(u8_t);
+ pbuf_header(p, -hlen);
+
+ type = *((u8_t *)p->payload);
+
+ switch(type) {
+ case ICMP_ECHO:
+ if(ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
+ ip_addr_ismulticast(&iphdr->dest)) {
+ DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
+#ifdef ICMP_STATS
+ ++stats.icmp.err;
+#endif /* ICMP_STATS */
+ pbuf_free(p);
+ return;
+ }
+ DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
+ DEBUGF(DEMO_DEBUG, ("Pong!\n"));
+ if(p->tot_len < sizeof(struct icmp_echo_hdr)) {
+ DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
+ pbuf_free(p);
+#ifdef ICMP_STATS
+ ++stats.icmp.lenerr;
+#endif /* ICMP_STATS */
+
+ return;
+ }
+ iecho = p->payload;
+ if(inet_chksum_pbuf(p) != 0) {
+ DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
+ pbuf_free(p);
+#ifdef ICMP_STATS
+ ++stats.icmp.chkerr;
+#endif /* ICMP_STATS */
+ return;
+ }
+ tmpaddr.addr = iphdr->src.addr;
+ iphdr->src.addr = iphdr->dest.addr;
+ iphdr->dest.addr = tmpaddr.addr;
+ ICMPH_TYPE_SET(iecho, ICMP_ER);
+ /* adjust the checksum */
+ if(iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
+ iecho->chksum += htons(ICMP_ECHO << 8) + 1;
+ } else {
+ iecho->chksum += htons(ICMP_ECHO << 8);
+ }
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+
+ pbuf_header(p, hlen);
+ ip_output_if(p, &(iphdr->src), IP_HDRINCL,
+ IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
+ break;
+ default:
+ DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type not supported.\n"));
+#ifdef ICMP_STATS
+ ++stats.icmp.proterr;
+ ++stats.icmp.drop;
+#endif /* ICMP_STATS */
+ }
+ pbuf_free(p);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
+{
+ struct pbuf *q;
+ struct ip_hdr *iphdr;
+ struct icmp_dur_hdr *idur;
+
+ q = pbuf_alloc(PBUF_TRANSPORT, 8 + IP_HLEN + 8, PBUF_RAM);
+ /* ICMP header + IP header + 8 bytes of data */
+
+ iphdr = p->payload;
+
+ idur = q->payload;
+ ICMPH_TYPE_SET(idur, ICMP_DUR);
+ ICMPH_CODE_SET(idur, t);
+
+ bcopy(p->payload, (char *)q->payload + 8, IP_HLEN + 8);
+
+ /* calculate checksum */
+ idur->chksum = 0;
+ idur->chksum = inet_chksum(idur, q->len);
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+
+ ip_output(q, NULL, &(iphdr->src),
+ ICMP_TTL, IP_PROTO_ICMP);
+ pbuf_free(q);
+}
+/*-----------------------------------------------------------------------------------*/
+#if IP_FORWARD
+void
+icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
+{
+ struct pbuf *q;
+ struct ip_hdr *iphdr;
+ struct icmp_te_hdr *tehdr;
+
+ q = pbuf_alloc(PBUF_TRANSPORT, 8 + IP_HLEN + 8, PBUF_RAM);
+
+ iphdr = p->payload;
+#if ICMP_DEBUG
+ DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
+ ip_addr_debug_print(&(iphdr->src));
+ DEBUGF(ICMP_DEBUG, (" to "));
+ ip_addr_debug_print(&(iphdr->dest));
+ DEBUGF(ICMP_DEBUG, ("\n"));
+#endif /* ICMP_DEBNUG */
+
+ tehdr = q->payload;
+ ICMPH_TYPE_SET(tehdr, ICMP_TE);
+ ICMPH_CODE_SET(tehdr, t);
+
+ /* copy fields from original packet */
+ bcopy((char *)p->payload, (char *)q->payload + 8, IP_HLEN + 8);
+
+ /* calculate checksum */
+ tehdr->chksum = 0;
+ tehdr->chksum = inet_chksum(tehdr, q->len);
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+ ip_output(q, NULL, &(iphdr->src),
+ ICMP_TTL, IP_PROTO_ICMP);
+ pbuf_free(q);
+}
+
+#endif /* IP_FORWARDING > 0 */
+
+
+
+
+
+
+
diff --git a/src/core/ipv4/ip.c b/src/core/ipv4/ip.c
new file mode 100644
index 0000000..d3d06f2
--- /dev/null
+++ b/src/core/ipv4/ip.c
@@ -0,0 +1,700 @@
+/*
+ * 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>
+ *
+ */
+
+
+/*-----------------------------------------------------------------------------------*/
+/* ip.c
+ *
+ * This is the code for the IP layer.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/ip.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/icmp.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "lwip/stats.h"
+
+#include "arch/perf.h"
+
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#endif /* LWIP_DHCP */
+
+/*-----------------------------------------------------------------------------------*/
+/* ip_init:
+ *
+ * Initializes the IP layer.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+ip_init(void)
+{
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_lookup:
+ *
+ * An experimental feature that will be changed in future versions. Do
+ * not depend on it yet...
+ */
+/*-----------------------------------------------------------------------------------*/
+#ifdef LWIP_DEBUG
+u8_t
+ip_lookup(void *header, struct netif *inp)
+{
+ struct ip_hdr *iphdr;
+
+ iphdr = header;
+
+ /* Refuse anything that isn't IPv4. */
+ if(IPH_V(iphdr) != 4) {
+ return 0;
+ }
+
+ /* Immediately accept/decline packets that are fragments or has
+ options. */
+#if IP_REASSEMBLY == 0
+ /* if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
+ return 0;
+ }*/
+#endif /* IP_REASSEMBLY == 0 */
+
+#if IP_OPTIONS == 0
+ if(IPH_HL(iphdr) != 5) {
+ return 0;
+ }
+#endif /* IP_OPTIONS == 0 */
+
+ switch(IPH_PROTO(iphdr)) {
+#if LWIP_UDP > 0
+ case IP_PROTO_UDP:
+ return udp_lookup(iphdr, inp);
+ break;
+#endif /* LWIP_UDP */
+#if LWIP_TCP > 0
+ case IP_PROTO_TCP:
+ return 1;
+#endif /* LWIP_TCP */
+ case IP_PROTO_ICMP:
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+}
+#endif /* LWIP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+/* ip_route:
+ *
+ * Finds the appropriate network interface for a given IP address. It
+ * searches the list of network interfaces linearly. A match is found
+ * if the masked IP address of the network interface equals the masked
+ * IP address given to the function.
+ */
+/*-----------------------------------------------------------------------------------*/
+struct netif *
+ip_route(struct ip_addr *dest)
+{
+ struct netif *netif;
+
+ for(netif = netif_list; netif != NULL; netif = netif->next) {
+ if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
+ return netif;
+ }
+ }
+
+ return netif_default;
+}
+#if IP_FORWARD
+/*-----------------------------------------------------------------------------------*/
+/* ip_forward:
+ *
+ * Forwards an IP packet. It finds an appropriate route for the
+ * packet, decrements the TTL value of the packet, adjusts the
+ * checksum and outputs the packet on the appropriate interface.
+ */
+/*-----------------------------------------------------------------------------------*/
+static void
+ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
+{
+ static struct netif *netif;
+
+ PERF_START;
+
+ if((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
+
+ DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
+ iphdr->dest.addr));
+
+ return;
+ }
+
+ /* Don't forward packets onto the same network interface on which
+ they arrived. */
+ if(netif == inp) {
+ DEBUGF(IP_DEBUG, ("ip_forward: not forward packets back on incoming interface.\n"));
+
+ return;
+ }
+
+ /* Decrement TTL and send ICMP if ttl == 0. */
+ IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
+ if(IPH_TTL(iphdr) == 0) {
+ /* Don't send ICMP messages in response to ICMP messages */
+ if(IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
+ icmp_time_exceeded(p, ICMP_TE_TTL);
+ }
+ return;
+ }
+
+ /* Incremental update of the IP checksum. */
+ if(IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
+ IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
+ } else {
+ IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
+ }
+
+ DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
+ iphdr->dest.addr));
+
+#ifdef IP_STATS
+ ++stats.ip.fw;
+ ++stats.ip.xmit;
+#endif /* IP_STATS */
+
+ PERF_STOP("ip_forward");
+
+ netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
+}
+#endif /* IP_FORWARD */
+/*-----------------------------------------------------------------------------------*/
+/* ip_reass:
+ *
+ * Tries to reassemble a fragmented IP packet.
+ */
+/*-----------------------------------------------------------------------------------*/
+#define IP_REASSEMBLY 1
+#define IP_REASS_BUFSIZE 5760
+#define IP_REASS_MAXAGE 10
+
+#if IP_REASSEMBLY
+static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
+static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)];
+static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
+ 0x0f, 0x07, 0x03, 0x01};
+static u16_t ip_reasslen;
+static u8_t ip_reassflags;
+#define IP_REASS_FLAG_LASTFRAG 0x01
+static u8_t ip_reasstmr;
+
+static struct pbuf *
+ip_reass(struct pbuf *p)
+{
+ struct pbuf *q;
+ struct ip_hdr *fraghdr, *iphdr;
+ u16_t offset, len;
+ u16_t i;
+
+ iphdr = (struct ip_hdr *)ip_reassbuf;
+ fraghdr = (struct ip_hdr *)p->payload;
+
+ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
+ write the IP header of the fragment into the reassembly
+ buffer. The timer is updated with the maximum age. */
+ if(ip_reasstmr == 0) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
+ bcopy(fraghdr, iphdr, IP_HLEN);
+ ip_reasstmr = IP_REASS_MAXAGE;
+ ip_reassflags = 0;
+ /* Clear the bitmap. */
+ bzero(ip_reassbitmap, sizeof(ip_reassbitmap));
+ }
+
+ /* Check if the incoming fragment matches the one currently present
+ in the reasembly buffer. If so, we proceed with copying the
+ fragment into the buffer. */
+ if(ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
+ ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
+ IPH_ID(iphdr) == IPH_ID(fraghdr)) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
+ /* Find out the offset in the reassembly buffer where we should
+ copy the fragment. */
+ len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
+ offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
+
+ /* If the offset or the offset + fragment length overflows the
+ reassembly buffer, we discard the entire packet. */
+ if(offset > IP_REASS_BUFSIZE ||
+ offset + len > IP_REASS_BUFSIZE) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: fragment outside of buffer (%d:%d/%d).\n",
+ offset, offset + len, IP_REASS_BUFSIZE));
+ ip_reasstmr = 0;
+ goto nullreturn;
+ }
+
+ /* Copy the fragment into the reassembly buffer, at the right
+ offset. */
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: copying with offset %d into %d:%d\n",
+ offset, IP_HLEN + offset, IP_HLEN + offset + len));
+ bcopy((u8_t *)fraghdr + IPH_HL(fraghdr) * 4,
+ &ip_reassbuf[IP_HLEN + offset], len);
+
+ /* Update the bitmap. */
+ if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: updating single byte in bitmap.\n"));
+ /* If the two endpoints are in the same byte, we only update
+ that byte. */
+ ip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7] &
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ } else {
+ /* If the two endpoints are in different bytes, we update the
+ bytes in the endpoints and fill the stuff inbetween with
+ 0xff. */
+ ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8 ) & 7];
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: updating many bytes in bitmap (%d:%d).\n",
+ 1 + offset / (8 * 8), (offset + len) / (8 * 8)));
+ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
+ ip_reassbitmap[i] = 0xff;
+ }
+ ip_reassbitmap[(offset + len) / (8 * 8)] |= ~bitmap_bits[((offset + len) / 8 ) & 7];
+ }
+
+ /* If this fragment has the More Fragments flag set to zero, we
+ know that this is the last fragment, so we can calculate the
+ size of the entire packet. We also set the
+ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
+ the final fragment. */
+
+ if((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
+ ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
+ ip_reasslen = offset + len;
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: last fragment seen, total len %d\n", ip_reasslen));
+ }
+
+ /* Finally, we check if we have a full packet in the buffer. We do
+ this by checking if we have the last fragment and if all bits
+ in the bitmap are set. */
+ if(ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
+ /* Check all bytes up to and including all but the last byte in
+ the bitmap. */
+ for(i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
+ if(ip_reassbitmap[i] != 0xff) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n", i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
+ goto nullreturn;
+ }
+ }
+ /* Check the last byte in the bitmap. It should contain just the
+ right amount of bits. */
+ if(ip_reassbitmap[ip_reasslen / (8 * 8)] !=
+ (u8_t)~bitmap_bits[ip_reasslen / 8 & 7]) {
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
+ ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
+ ip_reassbitmap[ip_reasslen / (8 * 8)]));
+ goto nullreturn;
+ }
+
+ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
+ from now on. */
+ IPH_OFFSET_SET(iphdr, 0);
+ IPH_CHKSUM_SET(iphdr, 0);
+ IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
+
+ /* If we have come this far, we have a full packet in the
+ buffer, so we allocate a pbuf and copy the packet into it. We
+ also reset the timer. */
+ ip_reasstmr = 0;
+ pbuf_free(p);
+ p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
+ if(p != NULL) {
+ i = 0;
+ for(q = p; q != NULL; q = q->next) {
+ /* Copy enough bytes to fill this pbuf in the chain. The
+ avaliable data in the pbuf is given by the q->len
+ variable. */
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: bcopy from %p (%d) to %p, %d bytes\n",
+ &ip_reassbuf[i], i, q->payload, q->len > ip_reasslen - i? ip_reasslen - i: q->len));
+ bcopy(&ip_reassbuf[i], q->payload,
+ q->len > ip_reasslen - i? ip_reasslen - i: q->len);
+ i += q->len;
+ }
+ }
+ DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", p));
+ return p;
+ }
+ }
+
+ nullreturn:
+ pbuf_free(p);
+ return NULL;
+}
+#endif /* IP_REASSEMBLY */
+/*-----------------------------------------------------------------------------------*/
+/* ip_input:
+ *
+ * This function is called by the network interface device driver when
+ * an IP packet is received. The function does the basic checks of the
+ * IP header such as packet size being at least larger than the header
+ * size etc. If the packet was not destined for us, the packet is
+ * forwarded (using ip_forward). The IP checksum is always checked.
+ *
+ * Finally, the packet is sent to the upper layer protocol input function.
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+ip_input(struct pbuf *p, struct netif *inp) {
+ static struct ip_hdr *iphdr;
+ static struct netif *netif;
+ static u8_t hl;
+
+
+
+#ifdef IP_STATS
+ ++stats.ip.recv;
+#endif /* IP_STATS */
+
+ /* identify the IP header */
+ iphdr = p->payload;
+ if(IPH_V(iphdr) != 4) {
+ DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number %d\n", IPH_V(iphdr)));
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+ pbuf_free(p);
+#ifdef IP_STATS
+ ++stats.ip.err;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return ERR_OK;
+ }
+
+ hl = IPH_HL(iphdr);
+
+ if(hl * 4 > p->len) {
+ DEBUGF(IP_DEBUG, ("IP packet dropped due to too short packet %d\n", p->len));
+
+ pbuf_free(p);
+#ifdef IP_STATS
+ ++stats.ip.lenerr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return ERR_OK;
+ }
+
+ /* verify checksum */
+ if(inet_chksum(iphdr, hl * 4) != 0) {
+
+ DEBUGF(IP_DEBUG, ("IP packet dropped due to failing checksum 0x%x\n", inet_chksum(iphdr, hl * 4)));
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+ pbuf_free(p);
+#ifdef IP_STATS
+ ++stats.ip.chkerr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return ERR_OK;
+ }
+
+ /* Trim pbuf. This should have been done at the netif layer,
+ but we'll do it anyway just to be sure that its done. */
+ pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
+
+ /* is this packet for us? */
+ for(netif = netif_list; netif != NULL; netif = netif->next) {
+
+ DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
+ iphdr->dest.addr, netif->ip_addr.addr,
+ iphdr->dest.addr & netif->netmask.addr,
+ netif->ip_addr.addr & netif->netmask.addr,
+ iphdr->dest.addr & ~(netif->netmask.addr)));
+
+ if(ip_addr_isany(&(netif->ip_addr)) ||
+ ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
+ (ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
+ ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
+ ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
+ break;
+ }
+ }
+
+#if LWIP_DHCP
+ /* If a DHCP packet has arrived on the interface, we pass it up the
+ stack regardless of destination IP address. The reason is that
+ DHCP replies are sent to the IP adress that will be given to this
+ node (as recommended by RFC 1542 section 3.1.1, referred by RFC
+ 2131). */
+ if(IPH_PROTO(iphdr) == IP_PROTO_UDP &&
+ ((struct udp_hdr *)((u8_t *)iphdr + IPH_HL(iphdr) * 4/sizeof(u8_t)))->src ==
+ DHCP_SERVER_PORT) {
+ netif = inp;
+ }
+#endif /* LWIP_DHCP */
+
+ if(netif == NULL) {
+ /* packet not for us, route or discard */
+ DEBUGF(IP_DEBUG, ("ip_input: packet not for us.\n"));
+#if IP_FORWARD
+ if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
+ ip_forward(p, iphdr, inp);
+ }
+#endif /* IP_FORWARD */
+ pbuf_free(p);
+ return ERR_OK;
+ }
+
+#if IP_REASSEMBLY
+ if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
+ p = ip_reass(p);
+ if(p == NULL) {
+ return ERR_OK;
+ }
+ iphdr = p->payload;
+ }
+#else /* IP_REASSEMBLY */
+ if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
+ pbuf_free(p);
+ DEBUGF(IP_DEBUG, ("IP packet dropped since it was fragmented (0x%x).\n",
+ ntohs(IPH_OFFSET(iphdr))));
+#ifdef IP_STATS
+ ++stats.ip.opterr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return ERR_OK;
+ }
+#endif /* IP_REASSEMBLY */
+
+#if IP_OPTIONS == 0
+ if(hl * 4 > IP_HLEN) {
+ DEBUGF(IP_DEBUG, ("IP packet dropped since there were IP options.\n"));
+
+ pbuf_free(p);
+#ifdef IP_STATS
+ ++stats.ip.opterr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return ERR_OK;
+ }
+#endif /* IP_OPTIONS == 0 */
+
+
+ /* send to upper layers */
+#if IP_DEBUG
+ DEBUGF(IP_DEBUG, ("ip_input: \n"));
+ ip_debug_print(p);
+ DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
+#endif /* IP_DEBUG */
+
+ switch(IPH_PROTO(iphdr)) {
+#if LWIP_UDP > 0
+ case IP_PROTO_UDP:
+ udp_input(p, inp);
+ break;
+#endif /* LWIP_UDP */
+#if LWIP_TCP > 0
+ case IP_PROTO_TCP:
+ tcp_input(p, inp);
+ break;
+#endif /* LWIP_TCP */
+ case IP_PROTO_ICMP:
+ icmp_input(p, inp);
+ break;
+ default:
+ /* send ICMP destination protocol unreachable unless is was a broadcast */
+ if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
+ !ip_addr_ismulticast(&(iphdr->dest))) {
+ p->payload = iphdr;
+ icmp_dest_unreach(p, ICMP_DUR_PROTO);
+ }
+ pbuf_free(p);
+
+ DEBUGF(IP_DEBUG, ("Unsupported transportation protocol %d\n", IPH_PROTO(iphdr)));
+
+#ifdef IP_STATS
+ ++stats.ip.proterr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+
+ }
+ return ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* ip_output_if:
+ *
+ * Sends an IP packet on a network interface. This function constructs
+ * the IP header and calculates the IP header checksum. If the source
+ * IP address is NULL, the IP address of the outgoing network
+ * interface is filled in as source address.
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl,
+ u8_t proto, struct netif *netif)
+{
+ static struct ip_hdr *iphdr;
+ static u16_t ip_id = 0;
+
+
+
+ if(dest != IP_HDRINCL) {
+ if(pbuf_header(p, IP_HLEN)) {
+ DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
+
+#ifdef IP_STATS
+ ++stats.ip.err;
+#endif /* IP_STATS */
+ return ERR_BUF;
+ }
+
+ iphdr = p->payload;
+
+ IPH_TTL_SET(iphdr, ttl);
+ IPH_PROTO_SET(iphdr, proto);
+
+ ip_addr_set(&(iphdr->dest), dest);
+
+ IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
+ IPH_LEN_SET(iphdr, htons(p->tot_len));
+ IPH_OFFSET_SET(iphdr, htons(IP_DF));
+ IPH_ID_SET(iphdr, htons(ip_id));
+ ++ip_id;
+
+ if(ip_addr_isany(src)) {
+ ip_addr_set(&(iphdr->src), &(netif->ip_addr));
+ } else {
+ ip_addr_set(&(iphdr->src), src);
+ }
+
+ IPH_CHKSUM_SET(iphdr, 0);
+ IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
+ } else {
+ iphdr = p->payload;
+ dest = &(iphdr->dest);
+ }
+
+#ifdef IP_STATS
+ stats.ip.xmit++;
+#endif /* IP_STATS */
+ DEBUGF(IP_DEBUG, ("ip_output_if: %c%c ", netif->name[0], netif->name[1]));
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+
+
+ return netif->output(netif, p, dest);
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_output:
+ *
+ * Simple interface to ip_output_if. It finds the outgoing network
+ * interface and calls upon ip_output_if to do the actual work.
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl, u8_t proto)
+{
+ static struct netif *netif;
+
+
+ if((netif = ip_route(dest)) == NULL) {
+ DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
+
+#ifdef IP_STATS
+ ++stats.ip.rterr;
+#endif /* IP_STATS */
+ pbuf_free(p);
+ return ERR_RTE;
+ }
+
+ return ip_output_if(p, src, dest, ttl, proto, netif);
+}
+/*-----------------------------------------------------------------------------------*/
+#if IP_DEBUG
+void
+ip_debug_print(struct pbuf *p)
+{
+ struct ip_hdr *iphdr = p->payload;
+ u8_t *payload;
+
+ payload = (u8_t *)iphdr + IP_HLEN/sizeof(u8_t);
+
+ DEBUGF(IP_DEBUG, ("IP header:\n"));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("|%2d |%2d | %2d | %4d | (v, hl, tos, len)\n",
+ IPH_V(iphdr),
+ IPH_HL(iphdr),
+ IPH_TOS(iphdr),
+ ntohs(IPH_LEN(iphdr))));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %5d |%d%d%d| %4d | (id, flags, offset)\n",
+ ntohs(IPH_ID(iphdr)),
+ ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
+ ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
+ ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
+ ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %2d | %2d | 0x%04x | (ttl, proto, chksum)\n",
+ IPH_TTL(iphdr),
+ IPH_PROTO(iphdr),
+ ntohs(IPH_CHKSUM(iphdr))));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
+ ntohl(iphdr->src.addr) >> 24 & 0xff,
+ ntohl(iphdr->src.addr) >> 16 & 0xff,
+ ntohl(iphdr->src.addr) >> 8 & 0xff,
+ ntohl(iphdr->src.addr) & 0xff));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
+ ntohl(iphdr->dest.addr) >> 24 & 0xff,
+ ntohl(iphdr->dest.addr) >> 16 & 0xff,
+ ntohl(iphdr->dest.addr) >> 8 & 0xff,
+ ntohl(iphdr->dest.addr) & 0xff));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+}
+#endif /* IP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
diff --git a/src/core/ipv4/ip_addr.c b/src/core/ipv4/ip_addr.c
new file mode 100644
index 0000000..fe95254
--- /dev/null
+++ b/src/core/ipv4/ip_addr.c
@@ -0,0 +1,41 @@
+/*
+ * 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/ip_addr.h"
+#include "lwip/inet.h"
+
+struct ip_addr ip_addr_broadcast = {0xffffffff};
+
+/*-----------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/ipv6/README b/src/core/ipv6/README
new file mode 100644
index 0000000..3620004
--- /dev/null
+++ b/src/core/ipv6/README
@@ -0,0 +1 @@
+IPv6 support in lwIP is very experimental.
diff --git a/src/core/ipv6/icmp6.c b/src/core/ipv6/icmp6.c
new file mode 100644
index 0000000..08a4a85
--- /dev/null
+++ b/src/core/ipv6/icmp6.c
@@ -0,0 +1,184 @@
+/*
+ * 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>
+ *
+ */
+
+/* Some ICMP messages should be passed to the transport protocols. This
+ is not implemented. */
+
+#include "lwip/debug.h"
+
+#include "lwip/icmp.h"
+#include "lwip/inet.h"
+#include "lwip/ip.h"
+#include "lwip/def.h"
+
+#include "lwip/stats.h"
+
+/*-----------------------------------------------------------------------------------*/
+void
+icmp_input(struct pbuf *p, struct netif *inp)
+{
+ unsigned char type;
+ struct icmp_echo_hdr *iecho;
+ struct ip_hdr *iphdr;
+ struct ip_addr tmpaddr;
+
+
+#ifdef ICMP_STATS
+ ++stats.icmp.recv;
+#endif /* ICMP_STATS */
+
+ type = ((char *)p->payload)[0];
+
+ switch(type) {
+ case ICMP6_ECHO:
+ DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
+
+ if(p->tot_len < sizeof(struct icmp_echo_hdr)) {
+ DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
+
+ pbuf_free(p);
+#ifdef ICMP_STATS
+ ++stats.icmp.lenerr;
+#endif /* ICMP_STATS */
+
+ return;
+ }
+ iecho = p->payload;
+ iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
+ if(inet_chksum_pbuf(p) != 0) {
+ DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
+
+#ifdef ICMP_STATS
+ ++stats.icmp.chkerr;
+#endif /* ICMP_STATS */
+ /* return;*/
+ }
+ DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
+ ip_addr_set(&tmpaddr, &(iphdr->src));
+ ip_addr_set(&(iphdr->src), &(iphdr->dest));
+ ip_addr_set(&(iphdr->dest), &tmpaddr);
+ iecho->type = ICMP6_ER;
+ /* adjust the checksum */
+ if(iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
+ iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
+ } else {
+ iecho->chksum += htons(ICMP6_ECHO << 8);
+ }
+ DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+
+ /* DEBUGF("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len);*/
+ ip_output_if(p, &(iphdr->src), IP_HDRINCL,
+ iphdr->hoplim, IP_PROTO_ICMP, inp);
+ break;
+ default:
+ DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type not supported.\n"));
+
+#ifdef ICMP_STATS
+ ++stats.icmp.proterr;
+ ++stats.icmp.drop;
+#endif /* ICMP_STATS */
+ }
+
+ pbuf_free(p);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
+{
+ struct pbuf *q;
+ struct ip_hdr *iphdr;
+ struct icmp_dur_hdr *idur;
+
+ q = pbuf_alloc(PBUF_TRANSPORT, 8 + IP_HLEN + 8, PBUF_RAM);
+ /* ICMP header + IP header + 8 bytes of data */
+
+ iphdr = p->payload;
+
+ idur = q->payload;
+ idur->type = (char)ICMP6_DUR;
+ idur->icode = (char)t;
+
+ bcopy(p->payload, (char *)q->payload + 8, IP_HLEN + 8);
+
+ /* calculate checksum */
+ idur->chksum = 0;
+ idur->chksum = inet_chksum(idur, q->len);
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+
+ ip_output(q, NULL,
+ (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
+ pbuf_free(q);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
+{
+ struct pbuf *q;
+ struct ip_hdr *iphdr;
+ struct icmp_te_hdr *tehdr;
+
+ DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
+
+ q = pbuf_alloc(PBUF_TRANSPORT, 8 + IP_HLEN + 8, PBUF_RAM);
+
+ iphdr = p->payload;
+
+ tehdr = q->payload;
+ tehdr->type = (char)ICMP6_TE;
+ tehdr->icode = (char)t;
+
+ /* copy fields from original packet */
+ bcopy((char *)p->payload, (char *)q->payload + 8, IP_HLEN + 8);
+
+ /* calculate checksum */
+ tehdr->chksum = 0;
+ tehdr->chksum = inet_chksum(tehdr, q->len);
+#ifdef ICMP_STATS
+ ++stats.icmp.xmit;
+#endif /* ICMP_STATS */
+ ip_output(q, NULL,
+ (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
+ pbuf_free(q);
+}
+
+
+
+
+
+
+
+
diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c
new file mode 100644
index 0000000..60d9390
--- /dev/null
+++ b/src/core/ipv6/ip6.c
@@ -0,0 +1,386 @@
+/*
+ * 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>
+ *
+ */
+
+
+/*-----------------------------------------------------------------------------------*/
+/* ip.c
+ *
+ * This is the code for the IP layer for IPv6.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/ip.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/icmp.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "lwip/stats.h"
+
+#include "arch/perf.h"
+/*-----------------------------------------------------------------------------------*/
+/* ip_init:
+ *
+ * Initializes the IP layer.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+ip_init(void)
+{
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_route:
+ *
+ * Finds the appropriate network interface for a given IP address. It searches the
+ * list of network interfaces linearly. A match is found if the masked IP address of
+ * the network interface equals the masked IP address given to the function.
+ */
+/*-----------------------------------------------------------------------------------*/
+struct netif *
+ip_route(struct ip_addr *dest)
+{
+ struct netif *netif;
+
+ for(netif = netif_list; netif != NULL; netif = netif->next) {
+ if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
+ return netif;
+ }
+ }
+
+ return netif_default;
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_forward:
+ *
+ * Forwards an IP packet. It finds an appropriate route for the packet, decrements
+ * the TTL value of the packet, adjusts the checksum and outputs the packet on the
+ * appropriate interface.
+ */
+/*-----------------------------------------------------------------------------------*/
+static void
+ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
+{
+ struct netif *netif;
+
+ PERF_START;
+
+ if((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
+
+ DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
+#if IP_DEBUG
+ ip_addr_debug_print(&(iphdr->dest));
+#endif /* IP_DEBUG */
+ DEBUGF(IP_DEBUG, ("\n"));
+ pbuf_free(p);
+ return;
+ }
+ /* Decrement TTL and send ICMP if ttl == 0. */
+ if(--iphdr->hoplim == 0) {
+ /* Don't send ICMP messages in response to ICMP messages */
+ if(iphdr->nexthdr != IP_PROTO_ICMP) {
+ icmp_time_exceeded(p, ICMP_TE_TTL);
+ }
+ pbuf_free(p);
+ return;
+ }
+
+ /* Incremental update of the IP checksum. */
+ /* if (iphdr->chksum >= htons(0xffff - 0x100)) {
+ iphdr->chksum += htons(0x100) + 1;
+ } else {
+ iphdr->chksum += htons(0x100);
+ }*/
+
+
+ DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
+#if IP_DEBUG
+ ip_addr_debug_print(&(iphdr->dest));
+#endif /* IP_DEBUG */
+ DEBUGF(IP_DEBUG, ("\n"));
+
+#ifdef IP_STATS
+ ++stats.ip.fw;
+ ++stats.ip.xmit;
+#endif /* IP_STATS */
+
+ PERF_STOP("ip_forward");
+
+ netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_input:
+ *
+ * This function is called by the network interface device driver when an IP packet is
+ * received. The function does the basic checks of the IP header such as packet size
+ * being at least larger than the header size etc. If the packet was not destined for
+ * us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
+ *
+ * Finally, the packet is sent to the upper layer protocol input function.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+ip_input(struct pbuf *p, struct netif *inp) {
+ struct ip_hdr *iphdr;
+ struct netif *netif;
+
+
+ PERF_START;
+
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+
+
+#ifdef IP_STATS
+ ++stats.ip.recv;
+#endif /* IP_STATS */
+
+ /* identify the IP header */
+ iphdr = p->payload;
+
+
+ if(iphdr->v != 6) {
+ DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+ pbuf_free(p);
+#ifdef IP_STATS
+ ++stats.ip.err;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+ return;
+ }
+
+ /* is this packet for us? */
+ for(netif = netif_list; netif != NULL; netif = netif->next) {
+#if IP_DEBUG
+ DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
+ ip_addr_debug_print(&(iphdr->dest));
+ DEBUGF(IP_DEBUG, ("netif->ip_addr "));
+ ip_addr_debug_print(&(netif->ip_addr));
+ DEBUGF(IP_DEBUG, ("\n"));
+#endif /* IP_DEBUG */
+ if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
+ break;
+ }
+ }
+
+
+ if(netif == NULL) {
+ /* packet not for us, route or discard */
+#ifdef IP_FORWARD
+ ip_forward(p, iphdr);
+#endif
+ pbuf_free(p);
+ return;
+ }
+
+ pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
+
+ /* send to upper layers */
+#if IP_DEBUG
+ /* DEBUGF("ip_input: \n");
+ ip_debug_print(p);
+ DEBUGF("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len);*/
+#endif /* IP_DEBUG */
+
+
+ pbuf_header(p, -IP_HLEN);
+
+ switch(iphdr->nexthdr) {
+ case IP_PROTO_UDP:
+ udp_input(p);
+ break;
+ case IP_PROTO_TCP:
+ tcp_input(p);
+ break;
+ case IP_PROTO_ICMP:
+ icmp_input(p, inp);
+ break;
+ default:
+ /* send ICMP destination protocol unreachable */
+ icmp_dest_unreach(p, ICMP_DUR_PROTO);
+ pbuf_free(p);
+ DEBUGF(IP_DEBUG, ("Unsupported transportation protocol %d\n",
+ iphdr->nexthdr));
+
+#ifdef IP_STATS
+ ++stats.ip.proterr;
+ ++stats.ip.drop;
+#endif /* IP_STATS */
+
+ }
+ PERF_STOP("ip_input");
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* ip_output_if:
+ *
+ * Sends an IP packet on a network interface. This function constructs the IP header
+ * and calculates the IP header checksum. If the source IP address is NULL,
+ * the IP address of the outgoing network interface is filled in as source address.
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl,
+ u8_t proto, struct netif *netif)
+{
+ struct ip_hdr *iphdr;
+
+ PERF_START;
+
+ printf("len %d tot_len %d\n", p->len, p->tot_len);
+ if(pbuf_header(p, IP_HLEN)) {
+ DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
+#ifdef IP_STATS
+ ++stats.ip.err;
+#endif /* IP_STATS */
+
+ return ERR_BUF;
+ }
+ printf("len %d tot_len %d\n", p->len, p->tot_len);
+
+ iphdr = p->payload;
+
+
+ if(dest != IP_HDRINCL) {
+ printf("!IP_HDRLINCL\n");
+ iphdr->hoplim = ttl;
+ iphdr->nexthdr = proto;
+ iphdr->len = htons(p->tot_len - IP_HLEN);
+ ip_addr_set(&(iphdr->dest), dest);
+
+ iphdr->v = 6;
+
+ if(ip_addr_isany(src)) {
+ ip_addr_set(&(iphdr->src), &(netif->ip_addr));
+ } else {
+ ip_addr_set(&(iphdr->src), src);
+ }
+
+ } else {
+ dest = &(iphdr->dest);
+ }
+
+#ifdef IP_STATS
+ ++stats.ip.xmit;
+#endif /* IP_STATS */
+
+ DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %d)\n", netif->name[0], netif->name[1], p->tot_len));
+#if IP_DEBUG
+ ip_debug_print(p);
+#endif /* IP_DEBUG */
+
+ PERF_STOP("ip_output_if");
+ return netif->output(netif, p, dest);
+}
+/*-----------------------------------------------------------------------------------*/
+/* ip_output:
+ *
+ * Simple interface to ip_output_if. It finds the outgoing network interface and
+ * calls upon ip_output_if to do the actual work.
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl, u8_t proto)
+{
+ struct netif *netif;
+ if((netif = ip_route(dest)) == NULL) {
+ DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
+#ifdef IP_STATS
+ ++stats.ip.rterr;
+#endif /* IP_STATS */
+ return ERR_RTE;
+ }
+
+ return ip_output_if(p, src, dest, ttl, proto, netif);
+}
+/*-----------------------------------------------------------------------------------*/
+#if IP_DEBUG
+void
+ip_debug_print(struct pbuf *p)
+{
+ struct ip_hdr *iphdr = p->payload;
+ char *payload;
+
+ payload = (char *)iphdr + IP_HLEN;
+
+ DEBUGF(IP_DEBUG, ("IP header:\n"));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("|%2d | %x%x | %x%x | (v, traffic class, flow label)\n",
+ iphdr->v,
+ iphdr->tclass1, iphdr->tclass2,
+ iphdr->flow1, iphdr->flow2));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %5d | %2d | %2d | (len, nexthdr, hoplim)\n",
+ ntohs(iphdr->len),
+ iphdr->nexthdr,
+ iphdr->hoplim));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
+ ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
+ ntohl(iphdr->src.addr[0]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
+ ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
+ ntohl(iphdr->src.addr[1]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
+ ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
+ ntohl(iphdr->src.addr[2]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
+ ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
+ ntohl(iphdr->src.addr[3]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
+ ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
+ ntohl(iphdr->dest.addr[0]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
+ ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
+ ntohl(iphdr->dest.addr[1]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
+ ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
+ ntohl(iphdr->dest.addr[2]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
+ ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
+ ntohl(iphdr->dest.addr[3]) & 0xffff));
+ DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
+}
+#endif /* IP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/ipv6/ip6_addr.c b/src/core/ipv6/ip6_addr.c
new file mode 100644
index 0000000..f573d14
--- /dev/null
+++ b/src/core/ipv6/ip6_addr.c
@@ -0,0 +1,91 @@
+/*
+ * 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/ip_addr.h"
+#include "lwip/inet.h"
+
+/*-----------------------------------------------------------------------------------*/
+int
+ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
+ struct ip_addr *mask)
+{
+ return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
+ (addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) &&
+ (addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) &&
+ (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
+
+}
+/*-----------------------------------------------------------------------------------*/
+int
+ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
+{
+ return(addr1->addr[0] == addr2->addr[0] &&
+ addr1->addr[1] == addr2->addr[1] &&
+ addr1->addr[2] == addr2->addr[2] &&
+ addr1->addr[3] == addr2->addr[3]);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
+{
+ bcopy(src, dest, sizeof(struct ip_addr));
+ /* dest->addr[0] = src->addr[0];
+ dest->addr[1] = src->addr[1];
+ dest->addr[2] = src->addr[2];
+ dest->addr[3] = src->addr[3];*/
+}
+/*-----------------------------------------------------------------------------------*/
+int
+ip_addr_isany(struct ip_addr *addr)
+{
+ if(addr == NULL) return 1;
+ return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
+}
+
+/*-----------------------------------------------------------------------------------*/
+/*#if IP_DEBUG*/
+void
+ip_addr_debug_print(struct ip_addr *addr)
+{
+ printf("%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
+ ntohl(addr->addr[0]) >> 16 & 0xffff,
+ ntohl(addr->addr[0]) & 0xffff,
+ ntohl(addr->addr[1]) >> 16 & 0xffff,
+ ntohl(addr->addr[1]) & 0xffff,
+ ntohl(addr->addr[2]) >> 16 & 0xffff,
+ ntohl(addr->addr[2]) & 0xffff,
+ ntohl(addr->addr[3]) >> 16 & 0xffff,
+ ntohl(addr->addr[3]) & 0xffff);
+}
+/*#endif*/ /* IP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/mem.c b/src/core/mem.c
new file mode 100644
index 0000000..1e694eb
--- /dev/null
+++ b/src/core/mem.c
@@ -0,0 +1,297 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* mem.c
+ *
+ * Memory manager.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#include "lwip/debug.h"
+
+#include "lwip/arch.h"
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+
+#include "lwip/sys.h"
+
+#include "lwip/stats.h"
+
+struct mem {
+ mem_size_t next, prev;
+ u8_t used;
+#if MEM_ALIGNMENT == 2
+ u8_t dummy;
+#endif /* MEM_ALIGNEMNT == 2 */
+};
+
+static struct mem *ram_end;
+static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
+
+#define MIN_SIZE 12
+#define SIZEOF_STRUCT_MEM MEM_ALIGN_SIZE(sizeof(struct mem))
+/*#define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \
+ (((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : \
+ (4 - (sizeof(struct mem) % MEM_ALIGNMENT))))*/
+
+
+static struct mem *lfree; /* pointer to the lowest free block */
+
+static sys_sem_t mem_sem;
+
+/*-----------------------------------------------------------------------------------*/
+static void
+plug_holes(struct mem *mem)
+{
+ struct mem *nmem;
+ struct mem *pmem;
+
+ ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
+ ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
+ ASSERT("plug_holes: mem->used == 0", mem->used == 0);
+
+ /* plug hole forward */
+ ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
+
+ nmem = (struct mem *)&ram[mem->next];
+ if(mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
+ if(lfree == nmem) {
+ lfree = mem;
+ }
+ mem->next = nmem->next;
+ ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
+ }
+
+ /* plug hole backward */
+ pmem = (struct mem *)&ram[mem->prev];
+ if(pmem != mem && pmem->used == 0) {
+ if(lfree == mem) {
+ lfree = pmem;
+ }
+ pmem->next = mem->next;
+ ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+void
+mem_init(void)
+{
+ struct mem *mem;
+
+ bzero(ram, MEM_SIZE);
+ mem = (struct mem *)ram;
+ mem->next = MEM_SIZE;
+ mem->prev = 0;
+ mem->used = 0;
+ ram_end = (struct mem *)&ram[MEM_SIZE];
+ ram_end->used = 1;
+ ram_end->next = MEM_SIZE;
+ ram_end->prev = MEM_SIZE;
+
+ mem_sem = sys_sem_new(1);
+
+ lfree = (struct mem *)ram;
+
+#ifdef MEM_STATS
+ stats.mem.avail = MEM_SIZE;
+#endif /* MEM_STATS */
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+mem_malloc(mem_size_t size)
+{
+ mem_size_t ptr, ptr2;
+ struct mem *mem, *mem2;
+
+ if(size == 0) {
+ return NULL;
+ }
+
+ /* Expand the size of the allocated memory region so that we can
+ adjust for alignment. */
+ if((size % MEM_ALIGNMENT) != 0) {
+ size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
+ }
+
+ if(size > MEM_SIZE) {
+ return NULL;
+ }
+
+ sys_sem_wait(mem_sem);
+
+ for(ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
+ mem = (struct mem *)&ram[ptr];
+ if(!mem->used &&
+ mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
+ ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
+ mem2 = (struct mem *)&ram[ptr2];
+
+ mem2->prev = ptr;
+ mem2->next = mem->next;
+ mem->next = ptr2;
+ if(mem2->next != MEM_SIZE) {
+ ((struct mem *)&ram[mem2->next])->prev = ptr2;
+ }
+
+ mem2->used = 0;
+ mem->used = 1;
+#ifdef MEM_STATS
+ stats.mem.used += size;
+ /* if(stats.mem.max < stats.mem.used) {
+ stats.mem.max = stats.mem.used;
+ } */
+ if(stats.mem.max < ptr2) {
+ stats.mem.max = ptr2;
+ }
+#endif /* MEM_STATS */
+
+ if(mem == lfree) {
+ /* Find next free block after mem */
+ while(lfree->used && lfree != ram_end) {
+ lfree = (struct mem *)&ram[lfree->next];
+ }
+ ASSERT("mem_malloc: !lfree->used", !lfree->used);
+ }
+ sys_sem_signal(mem_sem);
+ ASSERT("mem_malloc: allocated memory not above ram_end.",
+ (u32_t)mem + SIZEOF_STRUCT_MEM + size <= (u32_t)ram_end);
+ ASSERT("mem_malloc: allocated memory properly aligned.",
+ (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
+ return (u8_t *)mem + SIZEOF_STRUCT_MEM;
+ }
+ }
+ DEBUGF(MEM_DEBUG, ("mem_malloc: could not allocate %d bytes\n", (int)size));
+#ifdef MEM_STATS
+ ++stats.mem.err;
+#endif /* MEM_STATS */
+ sys_sem_signal(mem_sem);
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+mem_free(void *rmem)
+{
+ struct mem *mem;
+
+ if(rmem == NULL) {
+ return;
+ }
+
+ sys_sem_wait(mem_sem);
+
+ ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
+ (u8_t *)rmem < (u8_t *)ram_end);
+
+
+ if((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
+ DEBUGF(MEM_DEBUG, ("mem_free: illegal memory\n"));
+#ifdef MEM_STATS
+ ++stats.mem.err;
+#endif /* MEM_STATS */
+ return;
+ }
+ mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
+
+ ASSERT("mem_free: mem->used", mem->used);
+
+ mem->used = 0;
+
+ if(mem < lfree) {
+ lfree = mem;
+ }
+
+#ifdef MEM_STATS
+ stats.mem.used -= mem->next - ((u8_t *)mem - ram) - SIZEOF_STRUCT_MEM;
+
+#endif /* MEM_STATS */
+ plug_holes(mem);
+ sys_sem_signal(mem_sem);
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+mem_reallocm(void *rmem, mem_size_t newsize)
+{
+ void *nmem;
+ nmem = mem_malloc(newsize);
+ if(nmem == NULL) {
+ return mem_realloc(rmem, newsize);
+ }
+ bcopy(rmem, nmem, newsize);
+ mem_free(rmem);
+ return nmem;
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+mem_realloc(void *rmem, mem_size_t newsize)
+{
+ mem_size_t size;
+ mem_size_t ptr, ptr2;
+ struct mem *mem, *mem2;
+
+ sys_sem_wait(mem_sem);
+
+ ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
+ (u8_t *)rmem < (u8_t *)ram_end);
+
+ if((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
+ DEBUGF(MEM_DEBUG, ("mem_free: illegal memory\n"));
+ return rmem;
+ }
+ mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
+
+ ptr = (u8_t *)mem - ram;
+
+ size = mem->next - ptr - SIZEOF_STRUCT_MEM;
+#ifdef MEM_STATS
+ stats.mem.used -= (size - newsize);
+#endif /* MEM_STATS */
+
+ if(newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
+ ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
+ mem2 = (struct mem *)&ram[ptr2];
+ mem2->used = 0;
+ mem2->next = mem->next;
+ mem2->prev = ptr;
+ mem->next = ptr2;
+ if(mem2->next != MEM_SIZE) {
+ ((struct mem *)&ram[mem2->next])->prev = ptr2;
+ }
+
+ plug_holes(mem2);
+ }
+ sys_sem_signal(mem_sem);
+ return rmem;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/memp.c b/src/core/memp.c
new file mode 100644
index 0000000..86ada63
--- /dev/null
+++ b/src/core/memp.c
@@ -0,0 +1,271 @@
+/*
+ * 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 "lwipopts.h"
+
+#include "lwip/memp.h"
+
+#include "lwip/pbuf.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+#include "lwip/api.h"
+#include "lwip/api_msg.h"
+#include "lwip/tcpip.h"
+
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+
+struct memp {
+ struct memp *next;
+};
+
+
+
+static struct memp *memp_tab[MEMP_MAX];
+
+static const u16_t memp_sizes[MEMP_MAX] = {
+ sizeof(struct pbuf),
+ sizeof(struct udp_pcb),
+ sizeof(struct tcp_pcb),
+ sizeof(struct tcp_pcb_listen),
+ sizeof(struct tcp_seg),
+ sizeof(struct netbuf),
+ sizeof(struct netconn),
+ sizeof(struct api_msg),
+ sizeof(struct tcpip_msg),
+ sizeof(struct sys_timeout)
+};
+
+static const u16_t memp_num[MEMP_MAX] = {
+ MEMP_NUM_PBUF,
+ MEMP_NUM_UDP_PCB,
+ MEMP_NUM_TCP_PCB,
+ MEMP_NUM_TCP_PCB_LISTEN,
+ MEMP_NUM_TCP_SEG,
+ MEMP_NUM_NETBUF,
+ MEMP_NUM_NETCONN,
+ MEMP_NUM_API_MSG,
+ MEMP_NUM_TCPIP_MSG,
+ MEMP_NUM_SYS_TIMEOUT
+};
+
+static u8_t memp_memory[(MEMP_NUM_PBUF *
+ MEM_ALIGN_SIZE(sizeof(struct pbuf) +
+ sizeof(struct memp)) +
+ MEMP_NUM_UDP_PCB *
+ MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
+ sizeof(struct memp)) +
+ MEMP_NUM_TCP_PCB *
+ MEM_ALIGN_SIZE(sizeof(struct tcp_pcb) +
+ sizeof(struct memp)) +
+ MEMP_NUM_TCP_PCB_LISTEN *
+ MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen) +
+ sizeof(struct memp)) +
+ MEMP_NUM_TCP_SEG *
+ MEM_ALIGN_SIZE(sizeof(struct tcp_seg) +
+ sizeof(struct memp)) +
+ MEMP_NUM_NETBUF *
+ MEM_ALIGN_SIZE(sizeof(struct netbuf) +
+ sizeof(struct memp)) +
+ MEMP_NUM_NETCONN *
+ MEM_ALIGN_SIZE(sizeof(struct netconn) +
+ sizeof(struct memp)) +
+ MEMP_NUM_API_MSG *
+ MEM_ALIGN_SIZE(sizeof(struct api_msg) +
+ sizeof(struct memp)) +
+ MEMP_NUM_TCPIP_MSG *
+ MEM_ALIGN_SIZE(sizeof(struct tcpip_msg) +
+ sizeof(struct memp)) +
+ MEMP_NUM_SYS_TIMEOUT *
+ MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
+ sizeof(struct memp)))];
+
+/*-----------------------------------------------------------------------------------*/
+static sys_sem_t mutex;
+/*-----------------------------------------------------------------------------------*/
+#ifdef LWIP_DEBUG
+static int
+memp_sanity(void)
+{
+ int i, c;
+ struct memp *m, *n;
+
+ for(i = 0; i < MEMP_MAX; i++) {
+ for(m = memp_tab[i]; m != NULL; m = m->next) {
+ c = 1;
+ for(n = memp_tab[i]; n != NULL; n = n->next) {
+ if(n == m) {
+ --c;
+ }
+ if(c < 0)
+ abort();
+ }
+ }
+ }
+ return 1;
+}
+#endif /* LWIP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+void
+memp_init(void)
+{
+ struct memp *m, *memp;
+ u16_t i, j;
+ u16_t size;
+
+#ifdef MEMP_STATS
+ for(i = 0; i < MEMP_MAX; ++i) {
+ stats.memp[i].used = stats.memp[i].max =
+ stats.memp[i].err = stats.memp[i].reclaimed = 0;
+ stats.memp[i].avail = memp_num[i];
+ }
+#endif /* MEMP_STATS */
+
+ memp = (struct memp *)&memp_memory[0];
+ for(i = 0; i < MEMP_MAX; ++i) {
+ size = MEM_ALIGN_SIZE(memp_sizes[i] + sizeof(struct memp));
+ if(memp_num[i] > 0) {
+ memp_tab[i] = memp;
+ m = memp;
+
+ for(j = 0; j < memp_num[i]; ++j) {
+ m->next = (struct memp *)MEM_ALIGN((u8_t *)m + size);
+ memp = m;
+ m = m->next;
+ }
+ memp->next = NULL;
+ memp = m;
+ } else {
+ memp_tab[i] = NULL;
+ }
+ }
+
+ mutex = sys_sem_new(1);
+
+
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+memp_malloc(memp_t type)
+{
+ struct memp *memp;
+
+ ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
+
+ memp = memp_tab[type];
+
+ if(memp != NULL) {
+ memp_tab[type] = memp->next;
+ memp->next = NULL;
+#ifdef MEMP_STATS
+ ++stats.memp[type].used;
+ if(stats.memp[type].used > stats.memp[type].max) {
+ stats.memp[type].max = stats.memp[type].used;
+ }
+#endif /* MEMP_STATS */
+ ASSERT("memp_malloc: memp properly aligned",
+ ((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
+
+ return MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
+ } else {
+ DEBUGF(MEMP_DEBUG, ("memp_malloc: out of memory in pool %d\n", type));
+#ifdef MEMP_STATS
+ ++stats.memp[type].err;
+#endif /* MEMP_STATS */
+ return NULL;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void *
+memp_mallocp(memp_t type)
+{
+ void *mem;
+ sys_sem_wait(mutex);
+ mem = memp_malloc(type);
+ sys_sem_signal(mutex);
+ return mem;
+}
+/*-----------------------------------------------------------------------------------*/
+#if 0
+void *
+memp_realloc(memp_t fromtype, memp_t totype, void *mem)
+{
+ void *rmem;
+ u16_t size;
+
+ if(mem == NULL) {
+ return NULL;
+ }
+
+ rmem = memp_malloc(totype);
+ if(rmem != NULL) {
+ size = memp_sizes[totype];
+ if(memp_sizes[fromtype] < size) {
+ size = memp_sizes[fromtype];
+ }
+ bcopy(mem, rmem, size);
+ memp_free(fromtype, mem);
+ }
+ return rmem;
+}
+#endif /* 0 */
+/*-----------------------------------------------------------------------------------*/
+void
+memp_free(memp_t type, void *mem)
+{
+ struct memp *memp;
+
+ if(mem == NULL) {
+ return;
+ }
+ memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
+
+#ifdef MEMP_STATS
+ stats.memp[type].used--;
+#endif /* MEMP_STATS */
+
+ memp->next = memp_tab[type];
+ memp_tab[type] = memp;
+
+ ASSERT("memp sanity", memp_sanity());
+
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+memp_freep(memp_t type, void *mem)
+{
+ sys_sem_wait(mutex);
+ memp_free(type, mem);
+ sys_sem_signal(mutex);
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/netif.c b/src/core/netif.c
new file mode 100644
index 0000000..130e6f7
--- /dev/null
+++ b/src/core/netif.c
@@ -0,0 +1,142 @@
+/*
+ * 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/def.h"
+#include "lwip/mem.h"
+#include "lwip/netif.h"
+
+struct netif *netif_list = NULL;
+struct netif *netif_default = NULL;
+
+/*-----------------------------------------------------------------------------------*/
+struct netif *
+netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
+ struct ip_addr *gw,
+ void (* init)(struct netif *netif),
+ err_t (* input)(struct pbuf *p, struct netif *netif))
+{
+ struct netif *netif;
+ static int netifnum = 0;
+
+ netif = mem_malloc(sizeof(struct netif));
+
+ if(netif == NULL) {
+ return NULL;
+ }
+
+ netif->num = netifnum++;
+ netif->input = input;
+ ip_addr_set(&(netif->ip_addr), ipaddr);
+ ip_addr_set(&(netif->netmask), netmask);
+ ip_addr_set(&(netif->gw), gw);
+
+ init(netif);
+
+ netif->next = netif_list;
+ netif_list = netif;
+#if NETIF_DEBUG
+ DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
+ netif->name[0], netif->name[1]));
+ ip_addr_debug_print(ipaddr);
+ DEBUGF(NETIF_DEBUG, (" netmask "));
+ ip_addr_debug_print(netmask);
+ DEBUGF(NETIF_DEBUG, (" gw "));
+ ip_addr_debug_print(gw);
+ DEBUGF(NETIF_DEBUG, ("\n"));
+#endif /* NETIF_DEBUG */
+ return netif;
+}
+/*-----------------------------------------------------------------------------------*/
+struct netif *
+netif_find(char *name)
+{
+ struct netif *netif;
+ u8_t num;
+
+ if(name == NULL) {
+ return NULL;
+ }
+
+ num = name[2] - '0';
+
+ for(netif = netif_list; netif != NULL; netif = netif->next) {
+ if(num == netif->num &&
+ name[0] == netif->name[0] &&
+ name[1] == netif->name[1]) {
+ DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name));
+ return netif;
+ }
+ }
+ DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name));
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
+{
+ ip_addr_set(&(netif->ip_addr), ipaddr);
+ DEBUGF(NETIF_DEBUG, ("netif: setting IP address of interface %c%c to %d.%d.%d.%d\n",
+ netif->name[0], netif->name[1],
+ (u8_t)(ntohl(ipaddr->addr) >> 24 & 0xff),
+ (u8_t)(ntohl(ipaddr->addr) >> 16 & 0xff),
+ (u8_t)(ntohl(ipaddr->addr) >> 8 & 0xff),
+ (u8_t)(ntohl(ipaddr->addr) & 0xff)));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netif_set_gw(struct netif *netif, struct ip_addr *gw)
+{
+ ip_addr_set(&(netif->gw), gw);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
+{
+ ip_addr_set(&(netif->netmask), netmask);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netif_set_default(struct netif *netif)
+{
+ netif_default = netif;
+ DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
+ netif->name[0], netif->name[1]));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+netif_init(void)
+{
+ netif_list = netif_default = NULL;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/pbuf.c b/src/core/pbuf.c
new file mode 100644
index 0000000..bbd7351
--- /dev/null
+++ b/src/core/pbuf.c
@@ -0,0 +1,597 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* pbuf.c
+ *
+ * Functions for the manipulation of pbufs. The pbufs holds all packets in the
+ * system.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#include "lwip/debug.h"
+
+#include "lwip/stats.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/pbuf.h"
+
+#include "lwip/sys.h"
+
+#include "arch/perf.h"
+
+static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
+static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
+static sys_sem_t pbuf_pool_free_sem;
+static struct pbuf *pbuf_pool = NULL;
+static struct pbuf *pbuf_pool_alloc_cache = NULL;
+static struct pbuf *pbuf_pool_free_cache = NULL;
+
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_init():
+ *
+ * Initializes the pbuf module. A large part of memory is allocated
+ * for holding the pool of pbufs. The size of the individual pbufs in
+ * the pool is given by the size parameter, and the number of pbufs in
+ * the pool by the num parameter.
+ *
+ * After the memory has been allocated, the pbufs are set up. The
+ * ->next pointer in each pbuf is set up to point to the next pbuf in
+ * the pool.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+pbuf_init(void)
+{
+ struct pbuf *p, *q;
+ u16_t i;
+
+ pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
+ ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
+
+#ifdef PBUF_STATS
+ stats.pbuf.avail = PBUF_POOL_SIZE;
+#endif /* PBUF_STATS */
+
+ /* Set up ->next pointers to link the pbufs of the pool together. */
+ p = pbuf_pool;
+
+ for(i = 0; i < PBUF_POOL_SIZE; ++i) {
+ p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
+ p->len = p->tot_len = PBUF_POOL_BUFSIZE;
+ p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
+ q = p;
+ p = p->next;
+ }
+
+ /* The ->next pointer of last pbuf is NULL to indicate that there
+ are no more pbufs in the pool. */
+ q->next = NULL;
+
+ pbuf_pool_alloc_lock = 0;
+ pbuf_pool_free_lock = 0;
+ pbuf_pool_free_sem = sys_sem_new(1);
+
+}
+/*-----------------------------------------------------------------------------------*/
+/* The following two functions are only called from pbuf_alloc(). */
+/*-----------------------------------------------------------------------------------*/
+static struct pbuf *
+pbuf_pool_alloc(void)
+{
+ struct pbuf *p = NULL;
+
+ /* First, see if there are pbufs in the cache. */
+ if(pbuf_pool_alloc_cache) {
+ p = pbuf_pool_alloc_cache;
+ if(p) {
+ pbuf_pool_alloc_cache = p->next;
+ }
+ } else {
+ /* Next, check the actual pbuf pool, but if the pool is locked, we
+ pretend to be out of buffers and return NULL. */
+ if(pbuf_pool_free_lock) {
+#ifdef PBUF_STATS
+ ++stats.pbuf.alloc_locked;
+#endif /* PBUF_STATS */
+ return NULL;
+ }
+ pbuf_pool_alloc_lock = 1;
+ if(!pbuf_pool_free_lock) {
+ p = pbuf_pool;
+ if(p) {
+ pbuf_pool = p->next;
+ }
+#ifdef PBUF_STATS
+ } else {
+ ++stats.pbuf.alloc_locked;
+#endif /* PBUF_STATS */
+ }
+ pbuf_pool_alloc_lock = 0;
+ }
+
+#ifdef PBUF_STATS
+ if(p != NULL) {
+ ++stats.pbuf.used;
+ if(stats.pbuf.used > stats.pbuf.max) {
+ stats.pbuf.max = stats.pbuf.used;
+ }
+ }
+#endif /* PBUF_STATS */
+
+ return p;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+pbuf_pool_free(struct pbuf *p)
+{
+ struct pbuf *q;
+
+#ifdef PBUF_STATS
+ for(q = p; q != NULL; q = q->next) {
+ --stats.pbuf.used;
+ }
+#endif /* PBUF_STATS */
+
+ if(pbuf_pool_alloc_cache == NULL) {
+ pbuf_pool_alloc_cache = p;
+ } else {
+ for(q = pbuf_pool_alloc_cache; q->next != NULL; q = q->next);
+ q->next = p;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_alloc():
+ *
+ * Allocates a pbuf at protocol layer l. The actual memory allocated
+ * for the pbuf is determined by the layer at which the pbuf is
+ * allocated and the requested size (from the size parameter). The
+ * flag parameter decides how and where the pbuf should be allocated
+ * as follows:
+ *
+ * * PBUF_RAM: buffer memory for pbuf is allocated as one large
+ * chunk. This includes protocol headers as well.
+ * * RBUF_ROM: no buffer memory is allocated for the pbuf, even for
+ * protocol headers. Additional headers must be prepended
+ * by allocating another pbuf and chain in to the front of
+ * the ROM pbuf.
+ * * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
+ * the pbuf pool that is allocated during pbuf_init().
+ */
+/*-----------------------------------------------------------------------------------*/
+struct pbuf *
+pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
+{
+ struct pbuf *p, *q, *r;
+ u16_t offset;
+ s32_t rsize;
+
+ offset = 0;
+ switch(l) {
+ case PBUF_TRANSPORT:
+ offset += PBUF_TRANSPORT_HLEN;
+ /* FALLTHROUGH */
+ case PBUF_IP:
+ offset += PBUF_IP_HLEN;
+ offset += PBUF_LINK_HLEN;
+ /* FALLTHROUGH */
+ case PBUF_LINK:
+ break;
+ case PBUF_RAW:
+ break;
+ default:
+ ASSERT("pbuf_alloc: bad pbuf layer", 0);
+ return NULL;
+ }
+
+ switch(flag) {
+ case PBUF_POOL:
+ /* Allocate head of pbuf chain into p. */
+ p = pbuf_pool_alloc();
+ if(p == NULL) {
+#ifdef PBUF_STATS
+ ++stats.pbuf.err;
+#endif /* PBUF_STATS */
+ return NULL;
+ }
+ p->next = NULL;
+
+ /* Set the payload pointer so that it points offset bytes into
+ pbuf data memory. */
+ p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
+
+ /* The total length of the pbuf is the requested size. */
+ p->tot_len = size;
+
+ /* Set the length of the first pbuf is the chain. */
+ p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;
+
+ p->flags = PBUF_FLAG_POOL;
+
+ /* Allocate the tail of the pbuf chain. */
+ r = p;
+ rsize = size - p->len;
+ while(rsize > 0) {
+ q = pbuf_pool_alloc();
+ if(q == NULL) {
+ DEBUGF(PBUF_DEBUG, ("pbuf_alloc: Out of pbufs in pool,\n"));
+#ifdef PBUF_STATS
+ ++stats.pbuf.err;
+#endif /* PBUF_STATS */
+ pbuf_pool_free(p);
+ return NULL;
+ }
+ q->next = NULL;
+ r->next = q;
+ q->len = rsize > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rsize;
+ q->flags = PBUF_FLAG_POOL;
+ q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
+ r = q;
+ q->ref = 1;
+ q = q->next;
+ rsize -= PBUF_POOL_BUFSIZE;
+ }
+ r->next = NULL;
+
+ ASSERT("pbuf_alloc: pbuf->payload properly aligned",
+ ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
+ break;
+ case PBUF_RAM:
+ /* If pbuf is to be allocated in RAM, allocate memory for it. */
+ p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + size + offset));
+ if(p == NULL) {
+ return NULL;
+ }
+ /* Set up internal structure of the pbuf. */
+ p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
+ p->len = p->tot_len = size;
+ p->next = NULL;
+ p->flags = PBUF_FLAG_RAM;
+
+ ASSERT("pbuf_alloc: pbuf->payload properly aligned",
+ ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
+ break;
+ case PBUF_ROM:
+ /* If the pbuf should point to ROM, we only need to allocate
+ memory for the pbuf structure. */
+ p = memp_mallocp(MEMP_PBUF);
+ if(p == NULL) {
+ return NULL;
+ }
+ p->payload = NULL;
+ p->len = p->tot_len = size;
+ p->next = NULL;
+ p->flags = PBUF_FLAG_ROM;
+ break;
+ default:
+ ASSERT("pbuf_alloc: erroneous flag", 0);
+ return NULL;
+ }
+ p->ref = 1;
+ return p;
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_refresh():
+ *
+ * Moves free buffers from the pbuf_pool_free_cache to the pbuf_pool
+ * list (if possible).
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+pbuf_refresh(void)
+{
+ struct pbuf *p;
+
+ sys_sem_wait(pbuf_pool_free_sem);
+
+ if(pbuf_pool_free_cache != NULL) {
+ pbuf_pool_free_lock = 1;
+ if(!pbuf_pool_alloc_lock) {
+ if(pbuf_pool == NULL) {
+ pbuf_pool = pbuf_pool_free_cache;
+ } else {
+ for(p = pbuf_pool; p->next != NULL; p = p->next);
+ p->next = pbuf_pool_free_cache;
+ }
+ pbuf_pool_free_cache = NULL;
+#ifdef PBUF_STATS
+ } else {
+ ++stats.pbuf.refresh_locked;
+#endif /* PBUF_STATS */
+ }
+
+ pbuf_pool_free_lock = 0;
+ }
+
+ sys_sem_signal(pbuf_pool_free_sem);
+}
+#define PBUF_POOL_FREE(p) do { \
+ sys_sem_wait(pbuf_pool_free_sem); \
+ p->next = pbuf_pool_free_cache; \
+ pbuf_pool_free_cache = p; \
+ sys_sem_signal(pbuf_pool_free_sem); \
+ } while(0)
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_realloc:
+ *
+ * Reallocates the memory for a pbuf. If the pbuf is in ROM, this as
+ * simple as to adjust the ->tot_len and ->len fields. If the pbuf is
+ * a pbuf chain, as it might be with both pbufs in dynamically
+ * allocated RAM and for pbufs from the pbuf pool, we have to step
+ * through the chain until we find the new endpoint in the pbuf chain.
+ * Then the pbuf that is right on the endpoint is resized and any
+ * further pbufs on the chain are deallocated.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+pbuf_realloc(struct pbuf *p, u16_t size)
+{
+ struct pbuf *q, *r;
+ u16_t rsize;
+
+ ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
+ p->flags == PBUF_FLAG_ROM ||
+ p->flags == PBUF_FLAG_RAM);
+
+
+ if(p->tot_len <= size) {
+ return;
+ }
+
+ switch(p->flags) {
+ case PBUF_FLAG_POOL:
+ /* First, step over any pbufs that should still be in the chain. */
+ rsize = size;
+ q = p;
+ while(rsize > q->len) {
+ rsize -= q->len;
+ q = q->next;
+ }
+ /* Adjust the length of the pbuf that will be halved. */
+ q->len = rsize;
+
+ /* And deallocate any left over pbufs. */
+ r = q->next;
+ q->next = NULL;
+ q = r;
+ while(q != NULL) {
+ r = q->next;
+ PBUF_POOL_FREE(q);
+#ifdef PBUF_STATS
+ --stats.pbuf.used;
+#endif /* PBUF_STATS */
+ q = r;
+ }
+ break;
+ case PBUF_FLAG_ROM:
+ p->len = size;
+ break;
+ case PBUF_FLAG_RAM:
+ /* First, step over the pbufs that should still be in the chain. */
+ rsize = size;
+ q = p;
+ while(rsize > q->len) {
+ rsize -= q->len;
+ q = q->next;
+ }
+ if(q->flags == PBUF_FLAG_RAM) {
+ /* Reallocate and adjust the length of the pbuf that will be halved. */
+ mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rsize);
+ }
+
+ q->len = rsize;
+
+ /* And deallocate any left over pbufs. */
+ r = q->next;
+ q->next = NULL;
+ q = r;
+ while(q != NULL) {
+ r = q->next;
+ pbuf_free(q);
+ q = r;
+ }
+ break;
+ }
+ p->tot_len = size;
+
+ pbuf_refresh();
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_header():
+ *
+ * Adjusts the ->payload pointer so that space for a header appears in
+ * the pbuf. Also, the ->tot_len and ->len fields are adjusted.
+ */
+/*-----------------------------------------------------------------------------------*/
+u8_t
+pbuf_header(struct pbuf *p, s16_t header_size)
+{
+ void *payload;
+
+ if(p->flags & PBUF_FLAG_ROM) {
+ return 1;
+ }
+
+ payload = p->payload;
+ p->payload = (u8_t *)p->payload - header_size/sizeof(u8_t);
+
+ DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size));
+
+ if((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
+ DEBUGF(PBUF_DEBUG, ("pbuf_header: failed %p %p\n",
+ (u8_t *)p->payload,
+ (u8_t *)p + sizeof(struct pbuf)));
+ p->payload = payload;
+ return 1;
+ }
+ p->len += header_size;
+ p->tot_len += header_size;
+
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_free():
+ *
+ * Decrements the reference count and deallocates the pbuf if the
+ * reference count is zero. If the pbuf is a chain all pbufs in the
+ * chain are deallocated.
+ */
+/*-----------------------------------------------------------------------------------*/
+u8_t
+pbuf_free(struct pbuf *p)
+{
+ struct pbuf *q;
+ u8_t count = 0;
+
+ if(p == NULL) {
+ return 0;
+ }
+
+ PERF_START;
+
+ ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
+ p->flags == PBUF_FLAG_ROM ||
+ p->flags == PBUF_FLAG_RAM);
+
+ ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
+
+ /* Decrement reference count. */
+ p->ref--;
+
+ q = NULL;
+ /* If reference count == 0, actually deallocate pbuf. */
+ if(p->ref == 0) {
+
+ while(p != NULL) {
+ /* Check if this is a pbuf from the pool. */
+ if(p->flags == PBUF_FLAG_POOL) {
+ p->len = p->tot_len = PBUF_POOL_BUFSIZE;
+ p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
+ q = p->next;
+ PBUF_POOL_FREE(p);
+#ifdef PBUF_STATS
+ --stats.pbuf.used;
+#endif /* PBUF_STATS */
+ } else if(p->flags == PBUF_FLAG_ROM) {
+ q = p->next;
+ memp_freep(MEMP_PBUF, p);
+ } else {
+ q = p->next;
+ mem_free(p);
+ }
+ p = q;
+ ++count;
+ }
+ pbuf_refresh();
+ }
+
+ PERF_STOP("pbuf_free");
+
+ return count;
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_clen():
+ *
+ * Returns the length of the pbuf chain.
+ */
+/*-----------------------------------------------------------------------------------*/
+u8_t
+pbuf_clen(struct pbuf *p)
+{
+ u8_t len;
+
+ if(p == NULL) {
+ return 0;
+ }
+
+ for(len = 0; p != NULL; p = p->next) {
+ ++len;
+ }
+ return len;
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_ref():
+ *
+ * Increments the reference count of the pbuf.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+pbuf_ref(struct pbuf *p)
+{
+ if(p == NULL) {
+ return;
+ }
+ ++(p->ref);
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_chain():
+ *
+ * Chains the two pbufs h and t together. The ->tot_len field of the
+ * first pbuf (h) is adjusted.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+pbuf_chain(struct pbuf *h, struct pbuf *t)
+{
+ struct pbuf *p;
+
+ if(t == NULL) {
+ return;
+ }
+ for(p = h; p->next != NULL; p = p->next);
+ p->next = t;
+ h->tot_len += t->tot_len;
+}
+/*-----------------------------------------------------------------------------------*/
+/* pbuf_dechain():
+ *
+ * Adjusts the ->tot_len field of the pbuf and returns the tail (if
+ * any) of the pbuf chain.
+ */
+/*-----------------------------------------------------------------------------------*/
+struct pbuf *
+pbuf_dechain(struct pbuf *p)
+{
+ struct pbuf *q;
+
+ q = p->next;
+ if (q != NULL) {
+ q->tot_len = p->tot_len - p->len;
+ }
+ p->tot_len = p->len;
+ p->next = NULL;
+ return q;
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/stats.c b/src/core/stats.c
new file mode 100644
index 0000000..8992e98
--- /dev/null
+++ b/src/core/stats.c
@@ -0,0 +1,54 @@
+/*
+ * 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/opt.h"
+
+#include "lwip/def.h"
+
+#include "lwip/stats.h"
+#include "lwip/mem.h"
+
+
+#ifdef STATS
+struct stats_ stats;
+#endif /* STATS */
+/*-----------------------------------------------------------------------------------*/
+void
+stats_init(void)
+{
+#ifdef STATS
+ bzero(&stats, sizeof(struct stats_));
+#endif /* STATS */
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/core/sys.c b/src/core/sys.c
new file mode 100644
index 0000000..011607c
--- /dev/null
+++ b/src/core/sys.c
@@ -0,0 +1,187 @@
+/*
+ * 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/sys.h"
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/memp.h"
+
+#ifndef NO_SYS
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_fetch(sys_mbox_t mbox, void **msg)
+{
+ u16_t time;
+ struct sys_timeouts *timeouts;
+ struct sys_timeout *tmptimeout;
+ sys_timeout_handler h;
+ void *arg;
+
+
+ again:
+ timeouts = sys_arch_timeouts();
+
+ if(timeouts->next == NULL) {
+ sys_arch_mbox_fetch(mbox, msg, 0);
+ } else {
+ if(timeouts->next->time > 0) {
+ time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
+ } else {
+ time = 0;
+ }
+
+ if(time == 0) {
+ /* If time == 0, a timeout occured before a message could be
+ fetched. We should now call the timeout handler and
+ deallocate the memory allocated for the timeout. */
+ tmptimeout = timeouts->next;
+ timeouts->next = tmptimeout->next;
+ h = tmptimeout->h;
+ arg = tmptimeout->arg;
+ memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
+ h(arg);
+
+ /* We try again to fetch a message from the mbox. */
+ goto again;
+ } else {
+ /* If time > 0, a message was received before the timeout
+ occured. The time variable is set to the number of
+ microseconds we waited for the message. */
+ if(time <= timeouts->next->time) {
+ timeouts->next->time -= time;
+ } else {
+ timeouts->next->time = 0;
+ }
+ }
+
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_sem_wait(sys_sem_t sem)
+{
+ u16_t time;
+ struct sys_timeouts *timeouts;
+ struct sys_timeout *tmptimeout;
+ sys_timeout_handler h;
+ void *arg;
+
+ /* while(sys_arch_sem_wait(sem, 1000) == 0);
+ return;*/
+
+ again:
+
+ timeouts = sys_arch_timeouts();
+
+ if(timeouts->next == NULL) {
+ sys_arch_sem_wait(sem, 0);
+ } else {
+ if(timeouts->next->time > 0) {
+ time = sys_arch_sem_wait(sem, timeouts->next->time);
+ } else {
+ time = 0;
+ }
+
+ if(time == 0) {
+ /* If time == 0, a timeout occured before a message could be
+ fetched. We should now call the timeout handler and
+ deallocate the memory allocated for the timeout. */
+ tmptimeout = timeouts->next;
+ timeouts->next = tmptimeout->next;
+ h = tmptimeout->h;
+ arg = tmptimeout->arg;
+ memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
+ h(arg);
+
+
+ /* We try again to fetch a message from the mbox. */
+ goto again;
+ } else {
+ /* If time > 0, a message was received before the timeout
+ occured. The time variable is set to the number of
+ microseconds we waited for the message. */
+ if(time <= timeouts->next->time) {
+ timeouts->next->time -= time;
+ } else {
+ timeouts->next->time = 0;
+ }
+ }
+
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg)
+{
+ struct sys_timeouts *timeouts;
+ struct sys_timeout *timeout, *t;
+
+ timeout = memp_malloc(MEMP_SYS_TIMEOUT);
+ if(timeout == NULL) {
+ return;
+ }
+ timeout->next = NULL;
+ timeout->h = h;
+ timeout->arg = arg;
+ timeout->time = msecs;
+
+ timeouts = sys_arch_timeouts();
+
+ if(timeouts->next == NULL) {
+ timeouts->next = timeout;
+ return;
+ }
+
+ if(timeouts->next->time > msecs) {
+ timeouts->next->time -= msecs;
+ timeout->next = timeouts->next;
+ timeouts->next = timeout;
+ } else {
+ for(t = timeouts->next; t != NULL; t = t->next) {
+ timeout->time -= t->time;
+ if(t->next == NULL ||
+ t->next->time > timeout->time) {
+ if(t->next != NULL) {
+ t->next->time -= timeout->time;
+ }
+ timeout->next = t->next;
+ t->next = timeout;
+ break;
+ }
+ }
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+#endif /* NO_SYS */
diff --git a/src/core/tcp.c b/src/core/tcp.c
new file mode 100644
index 0000000..8b0b161
--- /dev/null
+++ b/src/core/tcp.c
@@ -0,0 +1,1158 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* tcp.c
+ *
+ * This file contains common functions for the TCP implementation, such as functinos
+ * for manipulating the data structures and the TCP timer functions. TCP functions
+ * related to input and output is found in tcp_input.c and tcp_output.c respectively.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+
+#include "lwip/tcp.h"
+
+/* Incremented every coarse grained timer shot
+ (typically every 500 ms, determined by TCP_COARSE_TIMEOUT). */
+u32_t tcp_ticks;
+const u8_t tcp_backoff[13] =
+ { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
+
+/* The TCP PCB lists. */
+struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
+struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
+ state in which they accept or send
+ data. */
+struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
+
+struct tcp_pcb *tcp_tmp_pcb;
+
+#define MIN(x,y) (x) < (y)? (x): (y)
+
+static u8_t tcp_timer;
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_init():
+ *
+ * Initializes the TCP layer.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_init(void)
+{
+ /* Clear globals. */
+ tcp_listen_pcbs = NULL;
+ tcp_active_pcbs = NULL;
+ tcp_tw_pcbs = NULL;
+ tcp_tmp_pcb = NULL;
+
+ /* initialize timer */
+ tcp_ticks = 0;
+ tcp_timer = 0;
+
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_tmr():
+ *
+ * Called periodically to dispatch TCP timers.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_tmr(void)
+{
+ ++tcp_timer;
+ if(tcp_timer == 10) {
+ tcp_timer = 0;
+ }
+
+ if(tcp_timer & 1) {
+ /* Call tcp_fasttmr() every 200 ms, i.e., every other timer
+ tcp_tmr() is called. */
+ tcp_fasttmr();
+ }
+ if(tcp_timer == 0 || tcp_timer == 5) {
+ /* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
+ tcp_tmr() is called. */
+ tcp_slowtmr();
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_close():
+ *
+ * Closes the connection held by the PCB.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcp_close(struct tcp_pcb *pcb)
+{
+ err_t err;
+
+#if TCP_DEBUG
+ DEBUGF(TCP_DEBUG, ("tcp_close: closing in state "));
+ tcp_debug_print_state(pcb->state);
+ DEBUGF(TCP_DEBUG, ("\n"));
+#endif /* TCP_DEBUG */
+ switch(pcb->state) {
+ case LISTEN:
+ err = ERR_OK;
+ tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB_LISTEN, pcb);
+ pcb = NULL;
+ break;
+ case SYN_SENT:
+ err = ERR_OK;
+ tcp_pcb_remove(&tcp_active_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB, pcb);
+ pcb = NULL;
+ break;
+ case SYN_RCVD:
+ err = tcp_send_ctrl(pcb, TCP_FIN);
+ if(err == ERR_OK) {
+ pcb->state = FIN_WAIT_1;
+ }
+ break;
+ case ESTABLISHED:
+ err = tcp_send_ctrl(pcb, TCP_FIN);
+ if(err == ERR_OK) {
+ pcb->state = FIN_WAIT_1;
+ }
+ break;
+ case CLOSE_WAIT:
+ err = tcp_send_ctrl(pcb, TCP_FIN);
+ if(err == ERR_OK) {
+ pcb->state = LAST_ACK;
+ }
+ break;
+ default:
+ /* Has already been closed, do nothing. */
+ err = ERR_OK;
+ pcb = NULL;
+ break;
+ }
+
+ if(pcb != NULL && err == ERR_OK) {
+ err = tcp_output(pcb);
+ }
+ return err;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_abort()
+ *
+ * Aborts a connection by sending a RST to the remote host and deletes
+ * the local protocol control block. This is done when a connection is
+ * killed because of shortage of memory.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_abort(struct tcp_pcb *pcb)
+{
+ u32_t seqno, ackno;
+ u16_t remote_port, local_port;
+ struct ip_addr remote_ip, local_ip;
+#if LWIP_CALLBACK_API
+ void (* errf)(void *arg, err_t err);
+#endif /* LWIP_CALLBACK_API */
+ void *errf_arg;
+
+
+ /* Figure out on which TCP PCB list we are, and remove us. If we
+ are in an active state, call the receive function associated with
+ the PCB with a NULL argument, and send an RST to the remote end. */
+ if(pcb->state == TIME_WAIT) {
+ tcp_pcb_remove(&tcp_tw_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB, pcb);
+ } else {
+ seqno = pcb->snd_nxt;
+ ackno = pcb->rcv_nxt;
+ ip_addr_set(&local_ip, &(pcb->local_ip));
+ ip_addr_set(&remote_ip, &(pcb->remote_ip));
+ local_port = pcb->local_port;
+ remote_port = pcb->remote_port;
+#if LWIP_CALLBACK_API
+ errf = pcb->errf;
+#endif /* LWIP_CALLBACK_API */
+ errf_arg = pcb->callback_arg;
+ tcp_pcb_remove(&tcp_active_pcbs, pcb);
+ if(pcb->unacked != NULL) {
+ tcp_segs_free(pcb->unacked);
+ }
+ if(pcb->unsent != NULL) {
+ tcp_segs_free(pcb->unsent);
+ }
+#if TCP_QUEUE_OOSEQ
+ if(pcb->ooseq != NULL) {
+ tcp_segs_free(pcb->ooseq);
+ }
+#endif /* TCP_QUEUE_OOSEQ */
+ memp_free(MEMP_TCP_PCB, pcb);
+ TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
+ DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n"));
+ tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_bind():
+ *
+ * Binds the connection to a local portnumber and IP address. If the
+ * IP address is not given (i.e., ipaddr == NULL), the IP address of
+ * the outgoing network interface is used instead.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+{
+ struct tcp_pcb *cpcb;
+
+ /* Check if the address already is in use. */
+ for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
+ cpcb != NULL; cpcb = cpcb->next) {
+ if(cpcb->local_port == port) {
+ if(ip_addr_isany(&(cpcb->local_ip)) ||
+ ip_addr_isany(ipaddr) ||
+ ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+ return ERR_USE;
+ }
+ }
+ }
+ for(cpcb = tcp_active_pcbs;
+ cpcb != NULL; cpcb = cpcb->next) {
+ if(cpcb->local_port == port) {
+ if(ip_addr_isany(&(cpcb->local_ip)) ||
+ ip_addr_isany(ipaddr) ||
+ ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+ return ERR_USE;
+ }
+ }
+ }
+ if(!ip_addr_isany(ipaddr)) {
+ pcb->local_ip = *ipaddr;
+ }
+ pcb->local_port = port;
+ DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %d\n", port));
+ return ERR_OK;
+}
+#if LWIP_CALLBACK_API
+static err_t
+tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
+{
+ return ERR_ABRT;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_listen():
+ *
+ * Set the state of the connection to be LISTEN, which means that it
+ * is able to accept incoming connections. The protocol control block
+ * is reallocated in order to consume less memory. Setting the
+ * connection to LISTEN is an irreversible process.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+struct tcp_pcb *
+tcp_listen(struct tcp_pcb *pcb)
+{
+ struct tcp_pcb_listen *lpcb;
+
+ lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
+ if(lpcb == NULL) {
+ return NULL;
+ }
+ lpcb->callback_arg = pcb->callback_arg;
+ lpcb->local_port = pcb->local_port;
+ ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
+ memp_free(MEMP_TCP_PCB, pcb);
+#if LWIP_CALLBACK_API
+ lpcb->accept = tcp_accept_null;
+#endif /* LWIP_CALLBACK_API */
+ TCP_REG((struct tcp_pcb **)&tcp_listen_pcbs, (struct tcp_pcb *)lpcb);
+ return (struct tcp_pcb *)lpcb;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_recved():
+ *
+ * This function should be called by the application when it has
+ * processed the data. The purpose is to advertise a larger window
+ * when the data has been processed.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_recved(struct tcp_pcb *pcb, u16_t len)
+{
+ pcb->rcv_wnd += len;
+ if(pcb->rcv_wnd > TCP_WND) {
+ pcb->rcv_wnd = TCP_WND;
+ }
+ if(!(pcb->flags & TF_ACK_DELAY) &&
+ !(pcb->flags & TF_ACK_NOW)) {
+ tcp_ack(pcb);
+ }
+ DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %d bytes, wnd %u (%u).\n",
+ len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_new_port():
+ *
+ * A nastly hack featuring 'goto' statements that allocates a
+ * new TCP local port.
+ */
+/*-----------------------------------------------------------------------------------*/
+static u16_t
+tcp_new_port(void)
+{
+ struct tcp_pcb *pcb;
+ static u16_t port = 4096;
+
+ again:
+ if(++port > 0x7fff) {
+ port = 4096;
+ }
+
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->local_port == port) {
+ goto again;
+ }
+ }
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->local_port == port) {
+ goto again;
+ }
+ }
+ for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->local_port == port) {
+ goto again;
+ }
+ }
+ return port;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_connect():
+ *
+ * Connects to another host. The function given as the "connected"
+ * argument will be called when the connection has been established.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+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))
+{
+ u32_t optdata;
+ err_t ret;
+ u32_t iss;
+
+ DEBUGF(TCP_DEBUG, ("tcp_connect to port %d\n", port));
+ if(ipaddr != NULL) {
+ pcb->remote_ip = *ipaddr;
+ } else {
+ return ERR_VAL;
+ }
+ pcb->remote_port = port;
+ if(pcb->local_port == 0) {
+ pcb->local_port = tcp_new_port();
+ }
+ iss = tcp_next_iss();
+ pcb->rcv_nxt = 0;
+ pcb->snd_nxt = iss;
+ pcb->lastack = iss - 1;
+ pcb->snd_lbb = iss - 1;
+ pcb->rcv_wnd = TCP_WND;
+ pcb->snd_wnd = TCP_WND;
+ pcb->mss = TCP_MSS;
+ pcb->cwnd = 1;
+ pcb->ssthresh = pcb->mss * 10;
+ pcb->state = SYN_SENT;
+#if LWIP_CALLBACK_API
+ pcb->connected = connected;
+#endif /* LWIP_CALLBACK_API */
+ TCP_REG(&tcp_active_pcbs, pcb);
+
+ /* Build an MSS option */
+ optdata = HTONL(((u32_t)2 << 24) |
+ ((u32_t)4 << 16) |
+ (((u32_t)pcb->mss / 256) << 8) |
+ (pcb->mss & 255));
+
+ ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
+ if(ret == ERR_OK) {
+ tcp_output(pcb);
+ }
+ return ret;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_slowtmr():
+ *
+ * Called every 500 ms and implements the retransmission timer and the timer that
+ * removes PCBs that have been in TIME-WAIT for enough time. It also increments
+ * various timers such as the inactivity timer in each PCB.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_slowtmr(void)
+{
+ struct tcp_pcb *pcb, *pcb2, *prev;
+ u32_t eff_wnd;
+ u8_t pcb_remove; /* flag if a PCB should be removed */
+ err_t err;
+
+ ++tcp_ticks;
+
+ /* Steps through all of the active PCBs. */
+ prev = NULL;
+ pcb = tcp_active_pcbs;
+ while(pcb != NULL) {
+ ASSERT("tcp_timer_coarse: active pcb->state != CLOSED", pcb->state != CLOSED);
+ ASSERT("tcp_timer_coarse: active pcb->state != LISTEN", pcb->state != LISTEN);
+ ASSERT("tcp_timer_coarse: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
+
+ pcb_remove = 0;
+
+ if(pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
+ ++pcb_remove;
+ } else if(pcb->nrtx == TCP_MAXRTX) {
+ ++pcb_remove;
+ } else {
+ ++pcb->rtime;
+ if(pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
+
+ /* Time for a retransmission. */
+ DEBUGF(TCP_RTO_DEBUG, ("tcp_timer_coarse: rtime %ld pcb->rto %d\n",
+ tcp_ticks - pcb->rtime, pcb->rto));
+
+ /* Double retransmission time-out unless we are trying to
+ connect to somebody (i.e., we are in SYN_SENT). */
+ /* if(pcb->state != SYN_SENT) {
+ pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
+ }*/
+
+ tcp_rexmit(pcb);
+
+ /* Reduce congestion window and ssthresh. */
+ eff_wnd = MIN(pcb->cwnd, pcb->snd_wnd);
+ pcb->ssthresh = eff_wnd >> 1;
+ if(pcb->ssthresh < pcb->mss) {
+ pcb->ssthresh = pcb->mss * 2;
+ }
+ pcb->cwnd = pcb->mss;
+
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_rexmit_seg: cwnd %u ssthresh %u\n",
+ pcb->cwnd, pcb->ssthresh));
+ }
+ }
+
+ /* Check if this PCB has stayed too long in FIN-WAIT-2 */
+ if(pcb->state == FIN_WAIT_2) {
+ if((u32_t)(tcp_ticks - pcb->tmr) >
+ TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
+ ++pcb_remove;
+ }
+ }
+
+ /* If this PCB has queued out of sequence data, but has been
+ inactive for too long, will drop the data (it will eventually
+ be retransmitted). */
+#if TCP_QUEUE_OOSEQ
+ if(pcb->ooseq != NULL &&
+ (u32_t)tcp_ticks - pcb->tmr >=
+ pcb->rto * TCP_OOSEQ_TIMEOUT) {
+ tcp_segs_free(pcb->ooseq);
+ pcb->ooseq = NULL;
+ }
+#endif /* TCP_QUEUE_OOSEQ */
+
+ /* Check if this PCB has stayed too long in SYN-RCVD */
+ if(pcb->state == SYN_RCVD) {
+ if((u32_t)(tcp_ticks - pcb->tmr) >
+ TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
+ ++pcb_remove;
+ }
+ }
+
+
+ /* If the PCB should be removed, do it. */
+ if(pcb_remove) {
+ tcp_pcb_purge(pcb);
+ /* Remove PCB from tcp_active_pcbs list. */
+ if(prev != NULL) {
+ ASSERT("tcp_timer_coarse: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
+ prev->next = pcb->next;
+ } else {
+ /* This PCB was the first. */
+ ASSERT("tcp_timer_coarse: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
+ tcp_active_pcbs = pcb->next;
+ }
+
+ TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
+ /* if(pcb->errf != NULL) {
+ pcb->errf(pcb->callback_arg, ERR_ABRT);
+ }*/
+
+ pcb2 = pcb->next;
+ memp_free(MEMP_TCP_PCB, pcb);
+ pcb = pcb2;
+ } else {
+
+ /* We check if we should poll the connection. */
+ ++pcb->polltmr;
+ if(pcb->polltmr >= pcb->pollinterval) {
+ pcb->polltmr = 0;
+ TCP_EVENT_POLL(pcb, err);
+ /* pcb->poll(pcb->callback_arg, pcb);*/
+ if(err == ERR_OK) {
+ tcp_output(pcb);
+ }
+ }
+
+ prev = pcb;
+ pcb = pcb->next;
+ }
+ }
+
+
+ /* Steps through all of the TIME-WAIT PCBs. */
+ prev = NULL;
+ pcb = tcp_tw_pcbs;
+ while(pcb != NULL) {
+ ASSERT("tcp_timer_coarse: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
+ pcb_remove = 0;
+
+ /* Check if this PCB has stayed long enough in TIME-WAIT */
+ if((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
+ ++pcb_remove;
+ }
+
+
+
+ /* If the PCB should be removed, do it. */
+ if(pcb_remove) {
+ tcp_pcb_purge(pcb);
+ /* Remove PCB from tcp_tw_pcbs list. */
+ if(prev != NULL) {
+ ASSERT("tcp_timer_coarse: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
+ prev->next = pcb->next;
+ } else {
+ /* This PCB was the first. */
+ ASSERT("tcp_timer_coarse: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
+ tcp_tw_pcbs = pcb->next;
+ }
+ pcb2 = pcb->next;
+ memp_free(MEMP_TCP_PCB, pcb);
+ pcb = pcb2;
+ } else {
+ prev = pcb;
+ pcb = pcb->next;
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_fasttmr():
+ *
+ * Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_fasttmr(void)
+{
+ struct tcp_pcb *pcb;
+
+ /* send delayed ACKs */
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->flags & TF_ACK_DELAY) {
+ DEBUGF(TCP_DEBUG, ("tcp_timer_fine: delayed ACK\n"));
+ tcp_ack_now(pcb);
+ pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_segs_free():
+ *
+ * Deallocates a list of TCP segments (tcp_seg structures).
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+u8_t
+tcp_segs_free(struct tcp_seg *seg)
+{
+ u8_t count = 0;
+ struct tcp_seg *next;
+ again:
+ if(seg != NULL) {
+ next = seg->next;
+ count += tcp_seg_free(seg);
+ seg = next;
+ goto again;
+ }
+ return count;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_seg_free():
+ *
+ * Frees a TCP segment.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+u8_t
+tcp_seg_free(struct tcp_seg *seg)
+{
+ u8_t count = 0;
+
+ if(seg != NULL) {
+ if(seg->p == NULL) {
+ memp_free(MEMP_TCP_SEG, seg);
+ } else {
+ count = pbuf_free(seg->p);
+#if TCP_DEBUG
+ seg->p = NULL;
+#endif /* TCP_DEBUG */
+ memp_free(MEMP_TCP_SEG, seg);
+ }
+ }
+ return count;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_setprio():
+ *
+ * Sets the priority of a connection.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
+{
+ pcb->prio = prio;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_seg_copy():
+ *
+ * Returns a copy of the given TCP segment.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+struct tcp_seg *
+tcp_seg_copy(struct tcp_seg *seg)
+{
+ struct tcp_seg *cseg;
+
+ cseg = memp_malloc(MEMP_TCP_SEG);
+ if(cseg == NULL) {
+ return NULL;
+ }
+ bcopy(seg, cseg, sizeof(struct tcp_seg));
+ pbuf_ref(cseg->p);
+ return cseg;
+}
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+static err_t
+tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+ arg = arg;
+ if(p != NULL) {
+ pbuf_free(p);
+ } else if(err == ERR_OK) {
+ return tcp_close(pcb);
+ }
+ return ERR_OK;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+static void
+tcp_kill_prio(u8_t prio)
+{
+ struct tcp_pcb *pcb, *inactive;
+ u32_t inactivity;
+ u8_t mprio;
+
+
+ mprio = TCP_PRIO_MAX;
+
+ /* We kill the oldest active connection that has lower priority than
+ prio. */
+ inactivity = 0;
+ inactive = NULL;
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->prio <= prio &&
+ pcb->prio <= mprio &&
+ (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
+ inactivity = tcp_ticks - pcb->tmr;
+ inactive = pcb;
+ mprio = pcb->prio;
+ }
+ }
+ if(inactive != NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_mem_reclaim: killing oldest PCB 0x%p (%ld)\n",
+ inactive, inactivity));
+ tcp_abort(inactive);
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+static void
+tcp_kill_timewait(void)
+{
+ struct tcp_pcb *pcb, *inactive;
+ u32_t inactivity;
+
+ inactivity = 0;
+ inactive = NULL;
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ if((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
+ inactivity = tcp_ticks - pcb->tmr;
+ inactive = pcb;
+ }
+ }
+ if(inactive != NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_mem_reclaim: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
+ inactive, inactivity));
+ tcp_abort(inactive);
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------------*/
+struct tcp_pcb *
+tcp_alloc(u8_t prio)
+{
+ struct tcp_pcb *pcb;
+ u32_t iss;
+
+ pcb = memp_malloc(MEMP_TCP_PCB);
+ if(pcb == NULL) {
+ /* Try killing oldest connection in TIME-WAIT. */
+ DEBUGF(TCP_DEBUG, ("tcp_new: killing off oldest TIME-WAIT connection\n"));
+ tcp_kill_timewait();
+ pcb = memp_malloc(MEMP_TCP_PCB);
+ if(pcb == NULL) {
+ tcp_kill_prio(prio);
+ pcb = memp_malloc(MEMP_TCP_PCB);
+ }
+ }
+ if(pcb != NULL) {
+ bzero(pcb, sizeof(struct tcp_pcb));
+ pcb->prio = TCP_PRIO_NORMAL;
+ pcb->snd_buf = TCP_SND_BUF;
+ pcb->snd_queuelen = 0;
+ pcb->rcv_wnd = TCP_WND;
+ pcb->mss = TCP_MSS;
+ pcb->rto = 3000 / TCP_SLOW_INTERVAL;
+ pcb->sa = 0;
+ pcb->sv = 3000 / TCP_SLOW_INTERVAL;
+ pcb->rtime = 0;
+ pcb->cwnd = 1;
+ iss = tcp_next_iss();
+ pcb->snd_wl2 = iss;
+ pcb->snd_nxt = iss;
+ pcb->snd_max = iss;
+ pcb->lastack = iss;
+ pcb->snd_lbb = iss;
+ pcb->tmr = tcp_ticks;
+
+ pcb->polltmr = 0;
+
+#if LWIP_CALLBACK_API
+ pcb->recv = tcp_recv_null;
+#endif /* LWIP_CALLBACK_API */
+ }
+ return pcb;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_new():
+ *
+ * Creates a new TCP protocol control block but doesn't place it on
+ * any of the TCP PCB lists.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+struct tcp_pcb *
+tcp_new(void)
+{
+ return tcp_alloc(TCP_PRIO_NORMAL);
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_arg():
+ *
+ * Used to specify the argument that should be passed callback
+ * functions.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_arg(struct tcp_pcb *pcb, void *arg)
+{
+ pcb->callback_arg = arg;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_recv():
+ *
+ * Used to specify the function that should be called when a TCP
+ * connection receives data.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+void
+tcp_recv(struct tcp_pcb *pcb,
+ err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
+{
+ pcb->recv = recv;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_sent():
+ *
+ * Used to specify the function that should be called when TCP data
+ * has been successfully delivered to the remote host.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+void
+tcp_sent(struct tcp_pcb *pcb,
+ err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
+{
+ pcb->sent = sent;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_err():
+ *
+ * Used to specify the function that should be called when a fatal error
+ * has occured on the connection.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+void
+tcp_err(struct tcp_pcb *pcb,
+ void (* errf)(void *arg, err_t err))
+{
+ pcb->errf = errf;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_poll():
+ *
+ * Used to specify the function that should be called periodically
+ * from TCP. The interval is specified in terms of the TCP coarse
+ * timer interval, which is called twice a second.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_poll(struct tcp_pcb *pcb,
+ err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
+{
+#if LWIP_CALLBACK_API
+ pcb->poll = poll;
+#endif /* LWIP_CALLBACK_API */
+ pcb->pollinterval = interval;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_accept():
+ *
+ * Used for specifying the function that should be called when a
+ * LISTENing connection has been connected to another host.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_CALLBACK_API
+void
+tcp_accept(struct tcp_pcb *pcb,
+ err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
+{
+ ((struct tcp_pcb_listen *)pcb)->accept = accept;
+}
+#endif /* LWIP_CALLBACK_API */
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_pcb_purge():
+ *
+ * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_pcb_purge(struct tcp_pcb *pcb)
+{
+ if(pcb->state != CLOSED &&
+ pcb->state != TIME_WAIT &&
+ pcb->state != LISTEN) {
+
+ DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
+
+#if TCP_DEBUG
+ if(pcb->unsent != NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
+ }
+ if(pcb->unacked != NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
+ }
+ if(pcb->ooseq != NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
+ }
+#endif /* TCP_DEBUG */
+ tcp_segs_free(pcb->unsent);
+#if TCP_QUEUE_OOSEQ
+ tcp_segs_free(pcb->ooseq);
+#endif /* TCP_QUEUE_OOSEQ */
+ tcp_segs_free(pcb->unacked);
+ pcb->unacked = pcb->unsent =
+#if TCP_QUEUE_OOSEQ
+ pcb->ooseq =
+#endif /* TCP_QUEUE_OOSEQ */
+ NULL;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_pcb_remove():
+ *
+ * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
+{
+ TCP_RMV(pcblist, pcb);
+
+ tcp_pcb_purge(pcb);
+
+ /* if there is an outstanding delayed ACKs, send it */
+ if(pcb->state != TIME_WAIT &&
+ pcb->state != LISTEN &&
+ pcb->flags & TF_ACK_DELAY) {
+ pcb->flags |= TF_ACK_NOW;
+ tcp_output(pcb);
+ }
+ pcb->state = CLOSED;
+
+ ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_next_iss():
+ *
+ * Calculates a new initial sequence number for new connections.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+u32_t
+tcp_next_iss(void)
+{
+ static u32_t iss = 6510;
+
+ iss += tcp_ticks; /* XXX */
+ return iss;
+}
+/*-----------------------------------------------------------------------------------*/
+#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
+void
+tcp_debug_print(struct tcp_hdr *tcphdr)
+{
+ DEBUGF(TCP_DEBUG, ("TCP header:\n"));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n",
+ tcphdr->src, tcphdr->dest));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(TCP_DEBUG, ("| %08lu | (seq no)\n",
+ tcphdr->seqno));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n",
+ tcphdr->ackno));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(TCP_DEBUG, ("| %2d | |%d%d%d%d%d| %5d | (offset, flags (",
+ TCPH_FLAGS(tcphdr) >> 4 & 1,
+ TCPH_FLAGS(tcphdr) >> 4 & 1,
+ TCPH_FLAGS(tcphdr) >> 3 & 1,
+ TCPH_FLAGS(tcphdr) >> 2 & 1,
+ TCPH_FLAGS(tcphdr) >> 1 & 1,
+ TCPH_FLAGS(tcphdr) & 1,
+ tcphdr->wnd));
+ tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
+ DEBUGF(TCP_DEBUG, ("), win)\n"));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(TCP_DEBUG, ("| 0x%04x | %5d | (chksum, urgp)\n",
+ ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
+ DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_debug_print_state(enum tcp_state s)
+{
+ DEBUGF(TCP_DEBUG, ("State: "));
+ switch(s) {
+ case CLOSED:
+ DEBUGF(TCP_DEBUG, ("CLOSED\n"));
+ break;
+ case LISTEN:
+ DEBUGF(TCP_DEBUG, ("LISTEN\n"));
+ break;
+ case SYN_SENT:
+ DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
+ break;
+ case SYN_RCVD:
+ DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
+ break;
+ case ESTABLISHED:
+ DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
+ break;
+ case FIN_WAIT_1:
+ DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
+ break;
+ case FIN_WAIT_2:
+ DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
+ break;
+ case CLOSE_WAIT:
+ DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
+ break;
+ case CLOSING:
+ DEBUGF(TCP_DEBUG, ("CLOSING\n"));
+ break;
+ case LAST_ACK:
+ DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
+ break;
+ case TIME_WAIT:
+ DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
+ break;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_debug_print_flags(u8_t flags)
+{
+ if(flags & TCP_FIN) {
+ DEBUGF(TCP_DEBUG, ("FIN "));
+ }
+ if(flags & TCP_SYN) {
+ DEBUGF(TCP_DEBUG, ("SYN "));
+ }
+ if(flags & TCP_RST) {
+ DEBUGF(TCP_DEBUG, ("RST "));
+ }
+ if(flags & TCP_PSH) {
+ DEBUGF(TCP_DEBUG, ("PSH "));
+ }
+ if(flags & TCP_ACK) {
+ DEBUGF(TCP_DEBUG, ("ACK "));
+ }
+ if(flags & TCP_URG) {
+ DEBUGF(TCP_DEBUG, ("URG "));
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_debug_print_pcbs(void)
+{
+ struct tcp_pcb *pcb;
+ DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ DEBUGF(TCP_DEBUG, ("Local port %d, foreign port %d snd_nxt %lu rcv_nxt %lu ",
+ pcb->local_port, pcb->remote_port,
+ pcb->snd_nxt, pcb->rcv_nxt));
+ tcp_debug_print_state(pcb->state);
+ }
+ DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
+ for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
+ DEBUGF(TCP_DEBUG, ("Local port %d, foreign port %d snd_nxt %lu rcv_nxt %lu ",
+ pcb->local_port, pcb->remote_port,
+ pcb->snd_nxt, pcb->rcv_nxt));
+ tcp_debug_print_state(pcb->state);
+ }
+ DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ DEBUGF(TCP_DEBUG, ("Local port %d, foreign port %d snd_nxt %lu rcv_nxt %lu ",
+ pcb->local_port, pcb->remote_port,
+ pcb->snd_nxt, pcb->rcv_nxt));
+ tcp_debug_print_state(pcb->state);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+int
+tcp_pcbs_sane(void)
+{
+ struct tcp_pcb *pcb;
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
+ ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
+ ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
+ }
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
+ }
+ return 1;
+}
+#endif /* TCP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
diff --git a/src/core/tcp_input.c b/src/core/tcp_input.c
new file mode 100644
index 0000000..4bfd251
--- /dev/null
+++ b/src/core/tcp_input.c
@@ -0,0 +1,1122 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* tcp_input.c
+ *
+ * The input processing functions of TCP.
+ *
+ * These functions are generally called in the order (ip_input() ->) tcp_input() ->
+ * tcp_process() -> tcp_receive() (-> application).
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/opt.h"
+
+#include "lwip/netif.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+
+#include "lwip/inet.h"
+#include "lwip/tcp.h"
+
+#include "lwip/stats.h"
+
+#include "arch/perf.h"
+
+/* These variables are global to all functions involved in the input
+ processing of TCP segments. They are set by the tcp_input()
+ function. */
+static struct tcp_seg inseg;
+static struct tcp_hdr *tcphdr;
+static struct ip_hdr *iphdr;
+static u32_t seqno, ackno;
+static u8_t flags;
+static u16_t tcplen;
+
+static u8_t recv_flags;
+static struct pbuf *recv_data;
+
+struct tcp_pcb *tcp_input_pcb;
+
+/* Forward declarations. */
+static err_t tcp_process(struct tcp_pcb *pcb);
+static void tcp_receive(struct tcp_pcb *pcb);
+static void tcp_parseopt(struct tcp_pcb *pcb);
+
+static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
+static err_t tcp_timewait_input(struct tcp_pcb *pcb);
+
+/*-----------------------------------------------------------------------------------*/
+/* tcp_input:
+ *
+ * The initial input processing of TCP. It verifies the TCP header, demultiplexes
+ * the segment between the PCBs and passes it on to tcp_process(), which implements
+ * the TCP finite state machine. This function is called by the IP layer (in
+ * ip_input()).
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_input(struct pbuf *p, struct netif *inp)
+{
+ struct tcp_pcb *pcb, *prev;
+ struct tcp_pcb_listen *lpcb;
+ u8_t offset;
+ err_t err;
+
+
+ PERF_START;
+
+
+#ifdef TCP_STATS
+ ++stats.tcp.recv;
+#endif /* TCP_STATS */
+
+ iphdr = p->payload;
+ tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4/sizeof(u8_t));
+
+ pbuf_header(p, -(IPH_HL(iphdr) * 4/sizeof(u8_t)));
+
+ /* Don't even process incoming broadcasts/multicasts. */
+ if(ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) ||
+ ip_addr_ismulticast(&(iphdr->dest))) {
+ pbuf_free(p);
+ return;
+ }
+
+
+ /* Verify TCP checksum. */
+ if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len) != 0) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len)));
+#if TCP_DEBUG
+ tcp_debug_print(tcphdr);
+#endif /* TCP_DEBUG */
+#ifdef TCP_STATS
+ ++stats.tcp.chkerr;
+ ++stats.tcp.drop;
+#endif /* TCP_STATS */
+
+ pbuf_free(p);
+ return;
+ }
+
+
+ /* Move the payload pointer in the pbuf so that it points to the
+ TCP data instead of the TCP header. */
+ offset = TCPH_OFFSET(tcphdr) >> 4;
+ pbuf_header(p, -(offset * 4));
+
+ /* Convert fields in TCP header to host byte order. */
+ tcphdr->src = ntohs(tcphdr->src);
+ tcphdr->dest = ntohs(tcphdr->dest);
+ seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
+ ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
+ tcphdr->wnd = ntohs(tcphdr->wnd);
+
+ flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS;
+ tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0);
+
+ /* Demultiplex an incoming segment. First, we check if it is destined
+ for an active connection. */
+ prev = NULL;
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
+ ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
+ ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
+ if(pcb->remote_port == tcphdr->src &&
+ pcb->local_port == tcphdr->dest &&
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+
+ /* Move this PCB to the front of the list so that subsequent
+ lookups will be faster (we exploit locality in TCP segment
+ arrivals). */
+ ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
+ if(prev != NULL) {
+ prev->next = pcb->next;
+ pcb->next = tcp_active_pcbs;
+ tcp_active_pcbs = pcb;
+ }
+ ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
+ break;
+ }
+ prev = pcb;
+ }
+
+ if(pcb == NULL) {
+ /* If it did not go to an active connection, we check the connections
+ in the TIME-WAIT state. */
+
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
+ if(pcb->remote_port == tcphdr->src &&
+ pcb->local_port == tcphdr->dest &&
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+ /* We don't really care enough to move this PCB to the front
+ of the list since we are not very likely to receive that
+ many segments for connections in TIME-WAIT. */
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
+ tcp_timewait_input(pcb);
+ pbuf_free(p);
+ return;
+ }
+ }
+
+ /* Finally, if we still did not get a match, we check all PCBs that
+ are LISTENing for incomming connections. */
+ prev = NULL;
+ for(lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
+ if((ip_addr_isany(&(lpcb->local_ip)) ||
+ ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
+ lpcb->local_port == tcphdr->dest) {
+ /* Move this PCB to the front of the list so that subsequent
+ lookups will be faster (we exploit locality in TCP segment
+ arrivals). */
+ if(prev != NULL) {
+ ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
+ lpcb->next = tcp_listen_pcbs;
+ tcp_listen_pcbs = lpcb;
+ }
+
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
+ tcp_listen_input(lpcb);
+ pbuf_free(p);
+ return;
+ }
+ prev = (struct tcp_pcb *)lpcb;
+ }
+ }
+
+#if TCP_INPUT_DEBUG
+ DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
+ tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
+ DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
+#endif /* TCP_INPUT_DEBUG */
+
+
+ if(pcb != NULL) {
+ /* The incoming segment belongs to a connection. */
+#if TCP_INPUT_DEBUG
+#if TCP_DEBUG
+ tcp_debug_print_state(pcb->state);
+#endif /* TCP_DEBUG */
+#endif /* TCP_INPUT_DEBUG */
+
+ /* Set up a tcp_seg structure. */
+ inseg.next = NULL;
+ inseg.len = p->tot_len;
+ inseg.dataptr = p->payload;
+ inseg.p = p;
+ inseg.tcphdr = tcphdr;
+
+ recv_data = NULL;
+ recv_flags = 0;
+
+ tcp_input_pcb = pcb;
+ err = tcp_process(pcb);
+ tcp_input_pcb = NULL;
+ /* A return value of ERR_ABRT means that tcp_abort() was called
+ and that the pcb has been freed. If so, we don't do anything. */
+ if(err != ERR_ABRT) {
+ if(recv_flags & TF_RESET) {
+ /* TF_RESET means that the connection was reset by the other
+ end. We then call the error callback to inform the
+ application that the connection is dead before we
+ deallocate the PCB. */
+ TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
+ tcp_pcb_remove(&tcp_active_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB, pcb);
+ } else if(recv_flags & TF_CLOSED) {
+ /* The connection has been closed and we will deallocate the
+ PCB. */
+ tcp_pcb_remove(&tcp_active_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB, pcb);
+ } else {
+ err = ERR_OK;
+ /* If the application has registered a "sent" function to be
+ called when new send buffer space is avaliable, we call it
+ now. */
+ if(pcb->acked > 0) {
+ TCP_EVENT_SENT(pcb, pcb->acked, err);
+ }
+
+ if(recv_data != NULL) {
+ /* Notify application that data has been received. */
+ TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
+ }
+
+ /* If a FIN segment was received, we call the callback
+ function with a NULL buffer to indicate EOF. */
+ if(recv_flags & TF_GOT_FIN) {
+ TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
+ }
+ /* If there were no errors, we try to send something out. */
+ if(err == ERR_OK) {
+ tcp_output(pcb);
+ }
+ }
+ }
+
+
+ /* We deallocate the incoming pbuf. If it was buffered by the
+ application, the application should have called pbuf_ref() to
+ increase the reference counter in the pbuf. If so, the buffer
+ isn't actually deallocated by the call to pbuf_free(), only the
+ reference count is decreased. */
+ pbuf_free(inseg.p);
+#if TCP_INPUT_DEBUG
+#if TCP_DEBUG
+ tcp_debug_print_state(pcb->state);
+#endif /* TCP_DEBUG */
+#endif /* TCP_INPUT_DEBUG */
+
+ } else {
+ /* If no matching PCB was found, send a TCP RST (reset) to the
+ sender. */
+ DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
+ if(!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
+#ifdef TCP_STATS
+ ++stats.tcp.proterr;
+ ++stats.tcp.drop;
+#endif /* TCP_STATS */
+ tcp_rst(ackno, seqno + tcplen,
+ &(iphdr->dest), &(iphdr->src),
+ tcphdr->dest, tcphdr->src);
+ }
+ pbuf_free(p);
+ }
+
+ ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
+ PERF_STOP("tcp_input");
+}
+/*-----------------------------------------------------------------------------------*/
+/* tcp_listen_input():
+ *
+ * Called by tcp_input() when a segment arrives for a listening
+ * connection.
+ */
+/*-----------------------------------------------------------------------------------*/
+static err_t
+tcp_listen_input(struct tcp_pcb_listen *pcb)
+{
+ struct tcp_pcb *npcb;
+ u32_t optdata;
+
+ /* In the LISTEN state, we check for incoming SYN segments,
+ creates a new PCB, and responds with a SYN|ACK. */
+ if(flags & TCP_ACK) {
+ /* For incoming segments with the ACK flag set, respond with a
+ RST. */
+ DEBUGF(TCP_RST_DEBUG, ("tcp_process: ACK in LISTEN, sending reset\n"));
+ tcp_rst(ackno + 1, seqno + tcplen,
+ &(iphdr->dest), &(iphdr->src),
+ tcphdr->dest, tcphdr->src);
+ } else if(flags & TCP_SYN) {
+ DEBUGF(DEMO_DEBUG, ("TCP connection request %d -> %d.\n", tcphdr->src, tcphdr->dest));
+ npcb = tcp_alloc(pcb->prio);
+ /* If a new PCB could not be created (probably due to lack of memory),
+ we don't do anything, but rely on the sender will retransmit the
+ SYN at a time when we have more memory avaliable. */
+ if(npcb == NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
+#ifdef TCP_STATS
+ ++stats.tcp.memerr;
+#endif /* TCP_STATS */
+ return ERR_MEM;
+ }
+ /* Set up the new PCB. */
+ ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
+ npcb->local_port = pcb->local_port;
+ ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
+ npcb->remote_port = tcphdr->src;
+ npcb->state = SYN_RCVD;
+ npcb->rcv_nxt = seqno + 1;
+ npcb->snd_wnd = tcphdr->wnd;
+ npcb->ssthresh = npcb->snd_wnd;
+ npcb->snd_wl1 = seqno;
+ npcb->callback_arg = pcb->callback_arg;
+#if LWIP_CALLBACK_API
+ npcb->accept = pcb->accept;
+#endif /* LWIP_CALLBACK_API */
+
+ /* Register the new PCB so that we can begin receiving segments
+ for it. */
+ TCP_REG(&tcp_active_pcbs, npcb);
+
+ /* Parse any options in the SYN. */
+ tcp_parseopt(npcb);
+
+ /* Build an MSS option. */
+ optdata = HTONL(((u32_t)2 << 24) |
+ ((u32_t)4 << 16) |
+ (((u32_t)npcb->mss / 256) << 8) |
+ (npcb->mss & 255));
+ /* Send a SYN|ACK together with the MSS option. */
+ tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
+ return tcp_output(npcb);
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+/* tcp_timewait_input():
+ *
+ * Called by tcp_input() when a segment arrives for a connection in
+ * TIME_WAIT.
+ */
+/*-----------------------------------------------------------------------------------*/
+static err_t
+tcp_timewait_input(struct tcp_pcb *pcb)
+{
+ if(TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) {
+ pcb->rcv_nxt = seqno + tcplen;
+ }
+ if(tcplen > 0) {
+ tcp_ack_now(pcb);
+ }
+ return tcp_output(pcb);
+}
+/*-----------------------------------------------------------------------------------*/
+/* tcp_process
+ *
+ * Implements the TCP state machine. Called by tcp_input. In some
+ * states tcp_receive() is called to receive data. The tcp_seg
+ * argument will be freed by the caller (tcp_input()) unless the
+ * recv_data pointer in the pcb is set.
+ */
+/*-----------------------------------------------------------------------------------*/
+static err_t
+tcp_process(struct tcp_pcb *pcb)
+{
+ struct tcp_seg *rseg;
+ u8_t acceptable = 0;
+ err_t err;
+
+
+ err = ERR_OK;
+
+ /* Process incoming RST segments. */
+ if(flags & TCP_RST) {
+ /* First, determine if the reset is acceptable. */
+ if(pcb->state == SYN_SENT) {
+ if(ackno == pcb->snd_nxt) {
+ acceptable = 1;
+ }
+ } else {
+ if(TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
+ TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
+ acceptable = 1;
+ }
+ }
+
+ if(acceptable) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
+ ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
+ recv_flags = TF_RESET;
+ pcb->flags &= ~TF_ACK_DELAY;
+ return ERR_RST;
+ } else {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
+ seqno, pcb->rcv_nxt));
+ DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
+ seqno, pcb->rcv_nxt));
+ return ERR_OK;
+ }
+ }
+
+ /* Update the PCB (in)activity timer. */
+ pcb->tmr = tcp_ticks;
+
+ /* Do different things depending on the TCP state. */
+ switch(pcb->state) {
+ case SYN_SENT:
+ DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,
+ pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
+ if(flags & (TCP_ACK | TCP_SYN) &&
+ ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
+ pcb->rcv_nxt = seqno + 1;
+ pcb->lastack = ackno;
+ pcb->snd_wnd = pcb->snd_wl1 = tcphdr->wnd;
+ pcb->state = ESTABLISHED;
+ pcb->cwnd = pcb->mss;
+ --pcb->snd_queuelen;
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %d\n", pcb->snd_queuelen));
+ rseg = pcb->unacked;
+ pcb->unacked = rseg->next;
+ tcp_seg_free(rseg);
+
+ /* Parse any options in the SYNACK. */
+ tcp_parseopt(pcb);
+
+ /* Call the user specified function to call when sucessfully
+ connected. */
+ TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
+ tcp_ack(pcb);
+ }
+ break;
+ case SYN_RCVD:
+ if(flags & TCP_ACK &&
+ !(flags & TCP_RST)) {
+ if(TCP_SEQ_LT(pcb->lastack, ackno) &&
+ TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
+ pcb->state = ESTABLISHED;
+ DEBUGF(DEMO_DEBUG, ("TCP connection established %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ ASSERT("pcb->accept != NULL", pcb->accept != NULL);
+ /* Call the accept function. */
+ TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
+ if(err != ERR_OK) {
+ /* If the accept function returns with an error, we abort
+ the connection. */
+ tcp_abort(pcb);
+ return ERR_ABRT;
+ }
+ /* If there was any data contained within this ACK,
+ we'd better pass it on to the application as well. */
+ tcp_receive(pcb);
+ pcb->cwnd = pcb->mss;
+ }
+ }
+ break;
+ case CLOSE_WAIT:
+ /* FALLTHROUGH */
+ case ESTABLISHED:
+ tcp_receive(pcb);
+ if(flags & TCP_FIN) {
+ tcp_ack_now(pcb);
+ pcb->state = CLOSE_WAIT;
+ }
+ break;
+ case FIN_WAIT_1:
+ tcp_receive(pcb);
+ if(flags & TCP_FIN) {
+ if(flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ DEBUGF(DEMO_DEBUG,
+ ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ tcp_ack_now(pcb);
+ tcp_pcb_purge(pcb);
+ TCP_RMV(&tcp_active_pcbs, pcb);
+ pcb->state = TIME_WAIT;
+ TCP_REG(&tcp_tw_pcbs, pcb);
+ } else {
+ tcp_ack_now(pcb);
+ pcb->state = CLOSING;
+ }
+ } else if(flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ pcb->state = FIN_WAIT_2;
+ }
+ break;
+ case FIN_WAIT_2:
+ tcp_receive(pcb);
+ if(flags & TCP_FIN) {
+ DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ tcp_ack_now(pcb);
+ tcp_pcb_purge(pcb);
+ TCP_RMV(&tcp_active_pcbs, pcb);
+ pcb->state = TIME_WAIT;
+ TCP_REG(&tcp_tw_pcbs, pcb);
+ }
+ break;
+ case CLOSING:
+ tcp_receive(pcb);
+ if(flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ tcp_ack_now(pcb);
+ tcp_pcb_purge(pcb);
+ TCP_RMV(&tcp_active_pcbs, pcb);
+ pcb->state = TIME_WAIT;
+ TCP_REG(&tcp_tw_pcbs, pcb);
+ }
+ break;
+ case LAST_ACK:
+ tcp_receive(pcb);
+ if(flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ pcb->state = CLOSED;
+ recv_flags = TF_CLOSED;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+/* tcp_receive:
+ *
+ * Called by tcp_process. Checks if the given segment is an ACK for outstanding
+ * data, and if so frees the memory of the buffered data. Next, is places the
+ * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
+ * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
+ * i it has been removed from the buffer.
+ *
+ * If the incoming segment constitutes an ACK for a segment that was used for RTT
+ * estimation, the RTT is estimated here as well.
+ */
+/*-----------------------------------------------------------------------------------*/
+static void
+tcp_receive(struct tcp_pcb *pcb)
+{
+ struct tcp_seg *next, *prev, *cseg;
+ struct pbuf *p;
+ s32_t off;
+ int m;
+
+
+ if(flags & TCP_ACK) {
+ /* Update window. */
+ if(TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
+ (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
+ (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
+ pcb->snd_wnd = tcphdr->wnd;
+ pcb->snd_wl1 = seqno;
+ pcb->snd_wl2 = ackno;
+ DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %lu\n", pcb->snd_wnd));
+#if TCP_WND_DEBUG
+ } else {
+ if(pcb->snd_wnd != tcphdr->wnd) {
+ DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %lu snd_max %lu ackno %lu wl1 %lu seqno %lu wl2 %lu\n",
+ pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
+ }
+#endif /* TCP_WND_DEBUG */
+ }
+
+
+ if(pcb->lastack == ackno) {
+ ++pcb->dupacks;
+ if(pcb->dupacks >= 3 && pcb->unacked != NULL) {
+ if(!(pcb->flags & TF_INFR)) {
+ /* This is fast retransmit. Retransmit the first unacked segment. */
+ DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n",
+ pcb->dupacks, pcb->lastack,
+ ntohl(pcb->unacked->tcphdr->seqno)));
+ tcp_rexmit(pcb);
+ /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
+ pcb->ssthresh = UMAX((pcb->snd_max -
+ pcb->lastack) / 2,
+ 2 * pcb->mss);
+
+ pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
+ pcb->flags |= TF_INFR;
+ } else {
+ /* Inflate the congestion window, but not if it means that
+ the value overflows. */
+ if(pcb->cwnd + pcb->mss > pcb->cwnd) {
+ pcb->cwnd += pcb->mss;
+ }
+
+ }
+ }
+ } else if(TCP_SEQ_LT(pcb->lastack, ackno) &&
+ TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
+ /* We come here when the ACK acknowledges new data. */
+
+ /* Reset the "IN Fast Retransmit" flag, since we are no longer
+ in fast retransmit. Also reset the congestion window to the
+ slow start threshold. */
+ if(pcb->flags & TF_INFR) {
+ pcb->flags &= ~TF_INFR;
+ pcb->cwnd = pcb->ssthresh;
+ }
+
+ /* Reset the number of retransmissions. */
+ pcb->nrtx = 0;
+
+ /* Reset the retransmission time-out. */
+ pcb->rto = (pcb->sa >> 3) + pcb->sv;
+
+ /* Update the send buffer space. */
+ pcb->acked = ackno - pcb->lastack;
+ pcb->snd_buf += pcb->acked;
+
+ /* Reset the fast retransmit variables. */
+ pcb->dupacks = 0;
+ pcb->lastack = ackno;
+
+ /* Update the congestion control variables (cwnd and
+ ssthresh). */
+ if(pcb->state >= ESTABLISHED) {
+ if(pcb->cwnd < pcb->ssthresh) {
+ if(pcb->cwnd + pcb->mss > pcb->cwnd) {
+ pcb->cwnd += pcb->mss;
+ }
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
+ } else {
+ if(pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd > pcb->cwnd) {
+ pcb->cwnd += pcb->mss * pcb->mss / pcb->cwnd;
+ }
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
+ }
+ }
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
+ ackno,
+ pcb->unacked != NULL?
+ ntohl(pcb->unacked->tcphdr->seqno): 0,
+ pcb->unacked != NULL?
+ ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
+
+ /* Remove segment from the unacknowledged list if the incoming
+ ACK acknowlegdes them. */
+ while(pcb->unacked != NULL &&
+ TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
+ TCP_TCPLEN(pcb->unacked), ackno)) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
+ ntohl(pcb->unacked->tcphdr->seqno),
+ ntohl(pcb->unacked->tcphdr->seqno) +
+ TCP_TCPLEN(pcb->unacked)));
+
+ next = pcb->unacked;
+ pcb->unacked = pcb->unacked->next;
+
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));
+ pcb->snd_queuelen -= pbuf_clen(next->p);
+ tcp_seg_free(next);
+
+ DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unacked)\n", pcb->snd_queuelen));
+#ifdef LWIP_DEBUG
+ if(pcb->snd_queuelen != 0) {
+ ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
+ pcb->unsent != NULL);
+ }
+#endif /* LWIP_DEBUG */
+ }
+ pcb->polltmr = 0;
+ }
+
+ /* We go through the ->unsent list to see if any of the segments
+ on the list are acknowledged by the ACK. This may seem
+ strange since an "unsent" segment shouldn't be acked. The
+ rationale is that lwIP puts all outstanding segments on the
+ ->unsent list after a retransmission, so these segments may
+ in fact have been sent once. */
+ while(pcb->unsent != NULL &&
+ TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent),
+ ackno) &&
+ TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
+ ntohl(pcb->unsent->tcphdr->seqno),
+ ntohl(pcb->unsent->tcphdr->seqno) +
+ TCP_TCPLEN(pcb->unsent)));
+
+ next = pcb->unsent;
+ pcb->unsent = pcb->unsent->next;
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));
+ pcb->snd_queuelen -= pbuf_clen(next->p);
+ tcp_seg_free(next);
+ DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unsent)\n", pcb->snd_queuelen));
+#ifdef LWIP_DEBUG
+ if(pcb->snd_queuelen != 0) {
+ ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
+ pcb->unsent != NULL);
+ }
+#endif /* LWIP_DEBUG */
+
+ if(pcb->unsent != NULL) {
+ pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
+ }
+ }
+
+ /* End of ACK for new data processing. */
+
+ DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %d rtseq %lu ackno %lu\n",
+ pcb->rttest, pcb->rtseq, ackno));
+
+ /* RTT estimation calculations. This is done by checking if the
+ incoming segment acknowledges the segment we use to take a
+ round-trip time measurement. */
+ if(pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
+ m = tcp_ticks - pcb->rttest;
+
+ DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %d ticks (%d msec).\n",
+ m, m * TCP_SLOW_INTERVAL));
+
+ /* This is taken directly from VJs original code in his paper */
+ m = m - (pcb->sa >> 3);
+ pcb->sa += m;
+ if(m < 0) {
+ m = -m;
+ }
+ m = m - (pcb->sv >> 2);
+ pcb->sv += m;
+ pcb->rto = (pcb->sa >> 3) + pcb->sv;
+
+ DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %d (%d miliseconds)\n",
+ pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
+
+ pcb->rttest = 0;
+ }
+ }
+
+ /* If the incoming segment contains data, we must process it
+ further. */
+ if(tcplen > 0) {
+ /* This code basically does three things:
+
+ +) If the incoming segment contains data that is the next
+ in-sequence data, this data is passed to the application. This
+ might involve trimming the first edge of the data. The rcv_nxt
+ variable and the advertised window are adjusted.
+
+ +) If the incoming segment has data that is above the next
+ sequence number expected (->rcv_nxt), the segment is placed on
+ the ->ooseq queue. This is done by finding the appropriate
+ place in the ->ooseq queue (which is ordered by sequence
+ number) and trim the segment in both ends if needed. An
+ immediate ACK is sent to indicate that we received an
+ out-of-sequence segment.
+
+ +) Finally, we check if the first segment on the ->ooseq queue
+ now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
+ rcv_nxt > ooseq->seqno, we must trim the first edge of the
+ segment on ->ooseq before we adjust rcv_nxt. The data in the
+ segments that are now on sequence are chained onto the
+ incoming segment so that we only need to call the application
+ once.
+ */
+
+ /* First, we check if we must trim the first edge. We have to do
+ this if the sequence number of the incoming segment is less
+ than rcv_nxt, and the sequence number plus the length of the
+ segment is larger than rcv_nxt. */
+ if(TCP_SEQ_LT(seqno, pcb->rcv_nxt) &&
+ TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {
+ /* Trimming the first edge is done by pushing the payload
+ pointer in the pbuf downwards. This is somewhat tricky since
+ we do not want to discard the full contents of the pbuf up to
+ the new starting point of the data since we have to keep the
+ TCP header which is present in the first pbuf in the chain.
+
+ What is done is really quite a nasty hack: the first pbuf in
+ the pbuf chain is pointed to by inseg.p. Since we need to be
+ able to deallocate the whole pbuf, we cannot change this
+ inseg.p pointer to point to any of the later pbufs in the
+ chain. Instead, we point the ->payload pointer in the first
+ pbuf to data in one of the later pbufs. We also set the
+ inseg.data pointer to point to the right place. This way, the
+ ->p pointer will still point to the first pbuf, but the
+ ->p->payload pointer will point to data in another pbuf.
+
+ After we are done with adjusting the pbuf pointers we must
+ adjust the ->data pointer in the seg and the segment
+ length.*/
+ off = pcb->rcv_nxt - seqno;
+ if(inseg.p->len < off) {
+ p = inseg.p;
+ while(p->len < off) {
+ off -= p->len;
+ inseg.p->tot_len -= p->len;
+ p->len = 0;
+ p = p->next;
+ }
+ pbuf_header(p, -off);
+ } else {
+ pbuf_header(inseg.p, -off);
+ }
+ inseg.dataptr = inseg.p->payload;
+ inseg.len -= pcb->rcv_nxt - seqno;
+ inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
+ }
+
+ /* The sequence number must be within the window (above rcv_nxt
+ and below rcv_nxt + rcv_wnd) in order to be further
+ processed. */
+ if(TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
+ TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
+ if(pcb->rcv_nxt == seqno) {
+ /* The incoming segment is the next in sequence. We check if
+ we have to trim the end of the segment and update rcv_nxt
+ and pass the data to the application. */
+#if TCP_QUEUE_OOSEQ
+ if(pcb->ooseq != NULL &&
+ TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
+ /* We have to trim the second edge of the incoming
+ segment. */
+ inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
+ pbuf_realloc(inseg.p, inseg.len);
+ }
+#endif /* TCP_QUEUE_OOSEQ */
+
+ tcplen = TCP_TCPLEN(&inseg);
+
+ pcb->rcv_nxt += tcplen;
+
+ /* Update the receiver's (our) window. */
+ if(pcb->rcv_wnd < tcplen) {
+ pcb->rcv_wnd = 0;
+ } else {
+ pcb->rcv_wnd -= tcplen;
+ }
+
+ /* If there is data in the segment, we make preparations to
+ pass this up to the application. The ->recv_data variable
+ is used for holding the pbuf that goes to the
+ application. The code for reassembling out-of-sequence data
+ chains its data on this pbuf as well.
+
+ If the segment was a FIN, we set the TF_GOT_FIN flag that will
+ be used to indicate to the application that the remote side has
+ closed its end of the connection. */
+ if(inseg.p->tot_len > 0) {
+ recv_data = inseg.p;
+ /* Since this pbuf now is the responsibility of the
+ application, we delete our reference to it so that we won't
+ (mistakingly) deallocate it. */
+ inseg.p = NULL;
+ }
+ if(TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
+ recv_flags = TF_GOT_FIN;
+ }
+
+#if TCP_QUEUE_OOSEQ
+ /* We now check if we have segments on the ->ooseq queue that
+ is now in sequence. */
+ while(pcb->ooseq != NULL &&
+ pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
+
+ cseg = pcb->ooseq;
+ seqno = pcb->ooseq->tcphdr->seqno;
+
+ pcb->rcv_nxt += TCP_TCPLEN(cseg);
+ if(pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
+ pcb->rcv_wnd = 0;
+ } else {
+ pcb->rcv_wnd -= TCP_TCPLEN(cseg);
+ }
+ if(cseg->p->tot_len > 0) {
+ /* Chain this pbuf onto the pbuf that we will pass to
+ the application. */
+ if(pcb->recv_data) {
+ pbuf_chain(pcb->recv_data, cseg->p);
+ } else {
+ pcb->recv_data = cseg->p;
+ }
+ cseg->p = NULL;
+ }
+ if(flags & TCP_FIN) {
+ DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
+ recv_flags = TF_GOT_FIN;
+ }
+
+
+ pcb->ooseq = cseg->next;
+ tcp_seg_free(cseg);
+ }
+#endif /* TCP_QUEUE_OOSEQ */
+
+
+ /* Acknowledge the segment(s). */
+ tcp_ack(pcb);
+
+ } else {
+ /* We get here if the incoming segment is out-of-sequence. */
+ tcp_ack_now(pcb);
+#if TCP_QUEUE_OOSEQ
+ /* We queue the segment on the ->ooseq queue. */
+ if(pcb->ooseq == NULL) {
+ pcb->ooseq = tcp_seg_copy(&inseg);
+ } else {
+ /* If the queue is not empty, we walk through the queue and
+ try to find a place where the sequence number of the
+ incoming segment is between the sequence numbers of the
+ previous and the next segment on the ->ooseq queue. That is
+ the place where we put the incoming segment. If needed, we
+ trim the second edges of the previous and the incoming
+ segment so that it will fit into the sequence.
+
+ If the incoming segment has the same sequence number as a
+ segment on the ->ooseq queue, we discard the segment that
+ contains less data. */
+
+ prev = NULL;
+ for(next = pcb->ooseq; next != NULL; next = next->next) {
+ if(seqno == next->tcphdr->seqno) {
+ /* The sequence number of the incoming segment is the
+ same as the sequence number of the segment on
+ ->ooseq. We check the lengths to see which one to
+ discard. */
+ if(inseg.len > next->len) {
+ /* The incoming segment is larger than the old
+ segment. We replace the old segment with the new
+ one. */
+ cseg = tcp_seg_copy(&inseg);
+ if(cseg != NULL) {
+ cseg->next = next->next;
+ if(prev != NULL) {
+ prev->next = cseg;
+ } else {
+ pcb->ooseq = cseg;
+ }
+ }
+ break;
+ } else {
+ /* Either the lenghts are the same or the incoming
+ segment was smaller than the old one; in either
+ case, we ditch the incoming segment. */
+ break;
+ }
+ } else {
+ if(prev == NULL) {
+ if(TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
+ /* The sequence number of the incoming segment is lower
+ than the sequence number of the first segment on the
+ queue. We put the incoming segment first on the
+ queue. */
+
+ if(TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
+ /* We need to trim the incoming segment. */
+ inseg.len = next->tcphdr->seqno - seqno;
+ pbuf_realloc(inseg.p, inseg.len);
+ }
+ cseg = tcp_seg_copy(&inseg);
+ if(cseg != NULL) {
+ cseg->next = next;
+ pcb->ooseq = cseg;
+ }
+ break;
+ }
+ } else if(TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
+ TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
+ /* The sequence number of the incoming segment is in
+ between the sequence numbers of the previous and
+ the next segment on ->ooseq. We trim and insert the
+ incoming segment and trim the previous segment, if
+ needed. */
+ if(TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
+ /* We need to trim the incoming segment. */
+ inseg.len = next->tcphdr->seqno - seqno;
+ pbuf_realloc(inseg.p, inseg.len);
+ }
+
+ cseg = tcp_seg_copy(&inseg);
+ if(cseg != NULL) {
+ cseg->next = next;
+ prev->next = cseg;
+ if(TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
+ /* We need to trim the prev segment. */
+ prev->len = seqno - prev->tcphdr->seqno;
+ pbuf_realloc(prev->p, prev->len);
+ }
+ }
+ break;
+ }
+ /* If the "next" segment is the last segment on the
+ ooseq queue, we add the incoming segment to the end
+ of the list. */
+ if(next->next == NULL &&
+ TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
+ next->next = tcp_seg_copy(&inseg);
+ if(next->next != NULL) {
+ if(TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
+ /* We need to trim the last segment. */
+ next->len = seqno - next->tcphdr->seqno;
+ pbuf_realloc(next->p, next->len);
+ }
+ }
+ break;
+ }
+ }
+ prev = next;
+ }
+ }
+#endif /* TCP_QUEUE_OOSEQ */
+
+ }
+ }
+ } else {
+ /* Segments with length 0 is taken care of here. Segments that
+ fall out of the window are ACKed. */
+ if(TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
+ TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
+ tcp_ack_now(pcb);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * tcp_parseopt:
+ *
+ * Parses the options contained in the incoming segment. (Code taken
+ * from uIP with only small changes.)
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+static void
+tcp_parseopt(struct tcp_pcb *pcb)
+{
+ u8_t c;
+ u8_t *opts, opt;
+ u16_t mss;
+
+ opts = (u8_t *)tcphdr + TCP_HLEN;
+
+ /* Parse the TCP MSS option, if present. */
+ if((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
+ for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
+ opt = opts[c];
+ if(opt == 0x00) {
+ /* End of options. */
+ break;
+ } else if(opt == 0x01) {
+ ++c;
+ /* NOP option. */
+ } else if(opt == 0x02 &&
+ opts[c + 1] == 0x04) {
+ /* An MSS option with the right option length. */
+ mss = (opts[c + 2] << 8) | opts[c + 3];
+ pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
+
+ /* And we are done processing options. */
+ break;
+ } else {
+ if(opts[c + 1] == 0) {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ c += opts[c + 1];
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+
diff --git a/src/core/tcp_output.c b/src/core/tcp_output.c
new file mode 100644
index 0000000..afabd14
--- /dev/null
+++ b/src/core/tcp_output.c
@@ -0,0 +1,589 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* tcp_output.c
+ *
+ * The output functions of TCP.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/opt.h"
+
+#include "arch/lib.h"
+
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/sys.h"
+
+#include "lwip/netif.h"
+
+#include "lwip/inet.h"
+#include "lwip/tcp.h"
+
+#include "lwip/stats.h"
+
+
+#define MIN(x,y) (x) < (y)? (x): (y)
+
+
+
+/* Forward declarations.*/
+static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
+
+
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
+{
+ return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
+
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
+{
+ if(pcb->state == SYN_SENT ||
+ pcb->state == SYN_RCVD ||
+ pcb->state == ESTABLISHED ||
+ pcb->state == CLOSE_WAIT) {
+ if(len > 0) {
+ return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
+ }
+ return ERR_OK;
+ } else {
+ return ERR_CONN;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
+ u8_t flags, u8_t copy,
+ u8_t *optdata, u8_t optlen)
+{
+ struct pbuf *p;
+ struct tcp_seg *seg, *useg, *queue;
+ u32_t left, seqno;
+ u16_t seglen;
+ void *ptr;
+ u8_t queuelen;
+
+ left = len;
+ ptr = arg;
+
+ if(len > pcb->snd_buf) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too much data %d\n", len));
+ return ERR_MEM;
+ }
+
+ seqno = pcb->snd_lbb;
+
+ queue = NULL;
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d\n", pcb->snd_queuelen));
+ queuelen = pcb->snd_queuelen;
+ if(queuelen >= TCP_SND_QUEUELEN) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN));
+ goto memerr;
+ }
+
+#ifdef LWIP_DEBUG
+ if(pcb->snd_queuelen != 0) {
+ ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
+ pcb->unsent != NULL);
+ }
+#endif /* LWIP_DEBUG */
+
+ seg = NULL;
+ seglen = 0;
+
+ while(queue == NULL || left > 0) {
+
+ seglen = left > pcb->mss? pcb->mss: left;
+
+ /* allocate memory for tcp_seg, and fill in fields */
+ seg = memp_malloc(MEMP_TCP_SEG);
+ if(seg == NULL) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
+ goto memerr;
+ }
+ seg->next = NULL;
+ seg->p = NULL;
+
+
+ if(queue == NULL) {
+ queue = seg;
+ } else {
+ for(useg = queue; useg->next != NULL; useg = useg->next);
+ useg->next = seg;
+ }
+
+ /* If copy is set, memory should be allocated
+ and data copied into pbuf, otherwise data comes from
+ ROM or other static memory, and need not be copied. If
+ optdata is != NULL, we have options instead of data. */
+ if(optdata != NULL) {
+ if((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
+ goto memerr;
+ }
+ ++queuelen;
+ seg->dataptr = seg->p->payload;
+ } else if(copy) {
+ if((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf copy\n"));
+ goto memerr;
+ }
+ ++queuelen;
+ if(arg != NULL) {
+ bcopy(ptr, seg->p->payload, seglen);
+ }
+ seg->dataptr = seg->p->payload;
+ } else {
+ /* Do not copy the data. */
+ if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf non-copy\n"));
+ goto memerr;
+ }
+ ++queuelen;
+ p->payload = ptr;
+ seg->dataptr = ptr;
+ if((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
+ pbuf_free(p);
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
+ goto memerr;
+ }
+ ++queuelen;
+ pbuf_chain(seg->p, p);
+ }
+ if(queuelen > TCP_SND_QUEUELEN) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN));
+ goto memerr;
+ }
+
+ seg->len = seglen;
+ /* if((flags & TCP_SYN) || (flags & TCP_FIN)) {
+ ++seg->len;
+ }*/
+
+ /* build TCP header */
+ if(pbuf_header(seg->p, TCP_HLEN)) {
+
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
+
+#ifdef TCP_STATS
+ ++stats.tcp.err;
+#endif /* TCP_STATS */
+ goto memerr;
+ }
+ seg->tcphdr = seg->p->payload;
+ seg->tcphdr->src = htons(pcb->local_port);
+ seg->tcphdr->dest = htons(pcb->remote_port);
+ seg->tcphdr->seqno = htonl(seqno);
+ seg->tcphdr->urgp = 0;
+ TCPH_FLAGS_SET(seg->tcphdr, flags);
+ /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
+
+ if(optdata == NULL) {
+ TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
+ } else {
+ TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
+ /* Copy options into data portion of segment.
+ Options can thus only be sent in non data carrying
+ segments such as SYN|ACK. */
+ bcopy(optdata, seg->dataptr, optlen);
+ }
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
+ ntohl(seg->tcphdr->seqno),
+ ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
+ flags));
+
+ left -= seglen;
+ seqno += seglen;
+ ptr = (void *)((char *)ptr + seglen);
+ }
+
+
+ /* Go to the last segment on the ->unsent queue. */
+ if(pcb->unsent == NULL) {
+ useg = NULL;
+ } else {
+ for(useg = pcb->unsent; useg->next != NULL; useg = useg->next);
+ }
+
+ /* If there is room in the last pbuf on the unsent queue,
+ chain the first pbuf on the queue together with that. */
+ if(useg != NULL &&
+ TCP_TCPLEN(useg) != 0 &&
+ !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
+ !(flags & (TCP_SYN | TCP_FIN)) &&
+ useg->len + queue->len <= pcb->mss) {
+ /* Remove TCP header from first segment. */
+ pbuf_header(queue->p, -TCP_HLEN);
+ pbuf_chain(useg->p, queue->p);
+ useg->len += queue->len;
+ useg->next = queue->next;
+
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: chaining, new len %u\n", useg->len));
+ if(seg == queue) {
+ seg = NULL;
+ }
+ memp_free(MEMP_TCP_SEG, queue);
+ } else {
+ if(useg == NULL) {
+ pcb->unsent = queue;
+
+ } else {
+ useg->next = queue;
+ }
+ }
+ if((flags & TCP_SYN) || (flags & TCP_FIN)) {
+ ++len;
+ }
+ pcb->snd_lbb += len;
+ pcb->snd_buf -= len;
+ pcb->snd_queuelen = queuelen;
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
+#ifdef LWIP_DEBUG
+ if(pcb->snd_queuelen != 0) {
+ ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
+ pcb->unsent != NULL);
+
+ }
+#endif /* LWIP_DEBUG */
+
+ /* Set the PSH flag in the last segment that we enqueued, but only
+ if the segment has data (indicated by seglen > 0). */
+ if(seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
+ TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
+ }
+
+ return ERR_OK;
+ memerr:
+#ifdef TCP_STATS
+ ++stats.tcp.memerr;
+#endif /* TCP_STATS */
+
+ if(queue != NULL) {
+ tcp_segs_free(queue);
+ }
+#ifdef LWIP_DEBUG
+ if(pcb->snd_queuelen != 0) {
+ ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
+ pcb->unsent != NULL);
+
+ }
+#endif /* LWIP_DEBUG */
+ DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
+ return ERR_MEM;
+}
+/*-----------------------------------------------------------------------------------*/
+/* find out what we can send and send it */
+err_t
+tcp_output(struct tcp_pcb *pcb)
+{
+ struct pbuf *p;
+ struct tcp_hdr *tcphdr;
+ struct tcp_seg *seg, *useg;
+ u32_t wnd;
+#if TCP_CWND_DEBUG
+ int i = 0;
+#endif /* TCP_CWND_DEBUG */
+
+ /* First, check if we are invoked by the TCP input processing
+ code. If so, we do not output anything. Instead, we rely on the
+ input processing code to call us when input processing is done
+ with. */
+ if(tcp_input_pcb == pcb) {
+ return ERR_OK;
+ }
+
+ wnd = MIN(pcb->snd_wnd, pcb->cwnd);
+
+
+ seg = pcb->unsent;
+
+ /* If the TF_ACK_NOW flag is set, we check if there is data that is
+ to be sent. If data is to be sent out, we'll just piggyback our
+ acknowledgement with the outgoing segment. If no data will be
+ sent (either because the ->unsent queue is empty or because the
+ window doesn't allow it) we'll have to construct an empty ACK
+ segment and send it. */
+ if(pcb->flags & TF_ACK_NOW &&
+ (seg == NULL ||
+ ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
+ pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
+ p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM);
+ if(p == NULL) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: (ACK) could not allocate pbuf\n"));
+ return ERR_BUF;
+ }
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: sending ACK for %lu\n", pcb->rcv_nxt));
+ if(pbuf_header(p, TCP_HLEN)) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: (ACK) no room for TCP header in pbuf.\n"));
+
+#ifdef TCP_STATS
+ ++stats.tcp.err;
+#endif /* TCP_STATS */
+ pbuf_free(p);
+ return ERR_BUF;
+ }
+
+ tcphdr = p->payload;
+ tcphdr->src = htons(pcb->local_port);
+ tcphdr->dest = htons(pcb->remote_port);
+ tcphdr->seqno = htonl(pcb->snd_nxt);
+ tcphdr->ackno = htonl(pcb->rcv_nxt);
+ TCPH_FLAGS_SET(tcphdr, TCP_ACK);
+ tcphdr->wnd = htons(pcb->rcv_wnd);
+ tcphdr->urgp = 0;
+ TCPH_OFFSET_SET(tcphdr, 5 << 4);
+
+ tcphdr->chksum = 0;
+ tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
+ IP_PROTO_TCP, p->tot_len);
+
+ ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
+ IP_PROTO_TCP);
+ pbuf_free(p);
+
+ return ERR_OK;
+ }
+
+#if TCP_OUTPUT_DEBUG
+ if(seg == NULL) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
+ }
+#endif /* TCP_OUTPUT_DEBUG */
+#if TCP_CWND_DEBUG
+ if(seg == NULL) {
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
+ pcb->snd_wnd, pcb->cwnd, wnd,
+ pcb->lastack));
+ } else {
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
+ pcb->snd_wnd, pcb->cwnd, wnd,
+ ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
+ ntohl(seg->tcphdr->seqno), pcb->lastack));
+ }
+#endif /* TCP_CWND_DEBUG */
+
+ while(seg != NULL &&
+ ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
+ pcb->rtime = 0;
+#if TCP_CWND_DEBUG
+ DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
+ pcb->snd_wnd, pcb->cwnd, wnd,
+ ntohl(seg->tcphdr->seqno) + seg->len -
+ pcb->lastack,
+ ntohl(seg->tcphdr->seqno), pcb->lastack, i));
+ ++i;
+#endif /* TCP_CWND_DEBUG */
+
+ pcb->unsent = seg->next;
+
+ if(pcb->state != SYN_SENT) {
+ TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
+ pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
+ }
+
+ tcp_output_segment(seg, pcb);
+ pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
+ if(TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
+ pcb->snd_max = pcb->snd_nxt;
+ }
+ /* put segment on unacknowledged list if length > 0 */
+ if(TCP_TCPLEN(seg) > 0) {
+ seg->next = NULL;
+ if(pcb->unacked == NULL) {
+ pcb->unacked = seg;
+
+
+ } else {
+ for(useg = pcb->unacked; useg->next != NULL; useg = useg->next);
+ useg->next = seg;
+ }
+ /* seg->rtime = 0;*/
+ } else {
+ tcp_seg_free(seg);
+ }
+ seg = pcb->unsent;
+ }
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
+{
+ u16_t len;
+ struct netif *netif;
+
+ /* The TCP header has already been constructed, but the ackno and
+ wnd fields remain. */
+ seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
+
+ /* silly window avoidance */
+ if(pcb->rcv_wnd < pcb->mss) {
+ seg->tcphdr->wnd = 0;
+ } else {
+ seg->tcphdr->wnd = htons(pcb->rcv_wnd);
+ }
+
+ /* If we don't have a local IP address, we get one by
+ calling ip_route(). */
+ if(ip_addr_isany(&(pcb->local_ip))) {
+ netif = ip_route(&(pcb->remote_ip));
+ if(netif == NULL) {
+ return;
+ }
+ ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
+ }
+
+ pcb->rtime = 0;
+
+ if(pcb->rttest == 0) {
+ pcb->rttest = tcp_ticks;
+ pcb->rtseq = ntohl(seg->tcphdr->seqno);
+
+ DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
+ }
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
+ htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
+ seg->len));
+
+ len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
+
+ seg->p->len -= len;
+ seg->p->tot_len -= len;
+
+ seg->p->payload = seg->tcphdr;
+
+ seg->tcphdr->chksum = 0;
+ seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
+ &(pcb->local_ip),
+ &(pcb->remote_ip),
+ IP_PROTO_TCP, seg->p->tot_len);
+#ifdef TCP_STATS
+ ++stats.tcp.xmit;
+#endif /* TCP_STATS */
+
+ ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
+ IP_PROTO_TCP);
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_rst(u32_t seqno, u32_t ackno,
+ struct ip_addr *local_ip, struct ip_addr *remote_ip,
+ u16_t local_port, u16_t remote_port)
+{
+ struct pbuf *p;
+ struct tcp_hdr *tcphdr;
+ p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM);
+ if(p == NULL) {
+ if(p == NULL) {
+ DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
+ return;
+ }
+ }
+ if(pbuf_header(p, TCP_HLEN)) {
+ DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_send_data: no room for TCP header in pbuf.\n"));
+
+#ifdef TCP_STATS
+ ++stats.tcp.err;
+#endif /* TCP_STATS */
+ return;
+ }
+
+ tcphdr = p->payload;
+ tcphdr->src = htons(local_port);
+ tcphdr->dest = htons(remote_port);
+ tcphdr->seqno = htonl(seqno);
+ tcphdr->ackno = htonl(ackno);
+ TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
+ tcphdr->wnd = htons(TCP_WND);
+ tcphdr->urgp = 0;
+ TCPH_OFFSET_SET(tcphdr, 5 << 4);
+
+ tcphdr->chksum = 0;
+ tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
+ IP_PROTO_TCP, p->tot_len);
+
+#ifdef TCP_STATS
+ ++stats.tcp.xmit;
+#endif /* TCP_STATS */
+ ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
+ pbuf_free(p);
+ DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcp_rexmit(struct tcp_pcb *pcb)
+{
+ struct tcp_seg *seg;
+
+ if(pcb->unacked == NULL) {
+ return;
+ }
+
+ /* Move all unacked segments to the unsent queue. */
+ for(seg = pcb->unacked; seg->next != NULL; seg = seg->next);
+
+ seg->next = pcb->unsent;
+ pcb->unsent = pcb->unacked;
+
+ pcb->unacked = NULL;
+
+
+ pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
+
+ ++pcb->nrtx;
+ pcb->rtime = 0;
+
+ /* Don't take any rtt measurements after retransmitting. */
+ pcb->rttest = 0;
+
+ /* Do the actual retransmission. */
+ tcp_output(pcb);
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/udp.c b/src/core/udp.c
new file mode 100644
index 0000000..ef01492
--- /dev/null
+++ b/src/core/udp.c
@@ -0,0 +1,453 @@
+/*
+ * 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>
+ *
+ */
+
+/*-----------------------------------------------------------------------------------*/
+/* udp.c
+ *
+ * The code for the User Datagram Protocol UDP.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+#include "lwip/debug.h"
+
+#include "lwip/def.h"
+#include "lwip/memp.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/udp.h"
+#include "lwip/icmp.h"
+
+#include "lwip/stats.h"
+
+#include "arch/perf.h"
+
+/*-----------------------------------------------------------------------------------*/
+
+/* The list of UDP PCBs. */
+#if LWIP_UDP
+static struct udp_pcb *udp_pcbs = NULL;
+
+static struct udp_pcb *pcb_cache = NULL;
+#endif /* LWIP_UDP */
+
+#if UDP_DEBUG
+int udp_debug_print(struct udp_hdr *udphdr);
+#endif /* UDP_DEBUG */
+
+/*-----------------------------------------------------------------------------------*/
+void
+udp_init(void)
+{
+ udp_pcbs = pcb_cache = NULL;
+}
+
+#if LWIP_UDP
+/*-----------------------------------------------------------------------------------*/
+/* udp_lookup:
+ *
+ * An experimental feature that will be changed in future versions. Do
+ * not depend on it yet...
+ */
+/*-----------------------------------------------------------------------------------*/
+#ifdef LWIP_DEBUG
+u8_t
+udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
+{
+ struct udp_pcb *pcb;
+ struct udp_hdr *udphdr;
+ u16_t src, dest;
+
+ PERF_START;
+
+ udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4/sizeof(u8_t);
+
+ src = NTOHS(udphdr->src);
+ dest = NTOHS(udphdr->dest);
+
+ pcb = pcb_cache;
+ if(pcb != NULL &&
+ pcb->remote_port == src &&
+ pcb->local_port == dest &&
+ (ip_addr_isany(&pcb->remote_ip) ||
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+ return 1;
+ } else {
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->remote_port == src &&
+ pcb->local_port == dest &&
+ (ip_addr_isany(&pcb->remote_ip) ||
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+ pcb_cache = pcb;
+ break;
+ }
+ }
+
+ if(pcb == NULL) {
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ if(pcb->local_port == dest &&
+ (ip_addr_isany(&pcb->remote_ip) ||
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+ break;
+ }
+ }
+ }
+ }
+
+ PERF_STOP("udp_lookup");
+
+ if(pcb != NULL) {
+ return 1;
+ } else {
+ return 1;
+ }
+}
+#endif /* LWIP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+void
+udp_input(struct pbuf *p, struct netif *inp)
+{
+ struct udp_hdr *udphdr;
+ struct udp_pcb *pcb;
+ struct ip_hdr *iphdr;
+ u16_t src, dest;
+
+ PERF_START;
+
+#ifdef UDP_STATS
+ ++stats.udp.recv;
+#endif /* UDP_STATS */
+
+ iphdr = p->payload;
+
+ pbuf_header(p, -(UDP_HLEN + IPH_HL(iphdr) * 4));
+
+ udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
+
+ DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %d\n", p->tot_len));
+
+ src = NTOHS(udphdr->src);
+ dest = NTOHS(udphdr->dest);
+
+#if UDP_DEBUG
+ udp_debug_print(udphdr);
+#endif /* UDP_DEBUG */
+
+ /* Demultiplex packet. First, go for a perfect match. */
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ DEBUGF(UDP_DEBUG, ("udp_input: pcb local port %d (dgram %d)\n",
+ pcb->local_port, ntohs(udphdr->dest)));
+ if(pcb->remote_port == src &&
+ pcb->local_port == dest &&
+ (ip_addr_isany(&pcb->remote_ip) ||
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+ break;
+ }
+ }
+
+ if(pcb == NULL) {
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ DEBUGF(UDP_DEBUG, ("udp_input: pcb local port %d (dgram %d)\n",
+ pcb->local_port, dest));
+ if(pcb->local_port == dest &&
+ (ip_addr_isany(&pcb->remote_ip) ||
+ ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+ break;
+ }
+ }
+ }
+
+
+ /* Check checksum if this is a match or if it was directed at us. */
+ /* if(pcb != NULL ||
+ ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {*/
+ if(pcb != NULL) {
+ DEBUGF(UDP_DEBUG, ("udp_input: calculating checksum\n"));
+ pbuf_header(p, UDP_HLEN);
+#ifdef IPv6
+ if(iphdr->nexthdr == IP_PROTO_UDPLITE) {
+#else
+ if(IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
+#endif /* IPv4 */
+ /* Do the UDP Lite checksum */
+ if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
+ DEBUGF(UDP_DEBUG, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
+#ifdef UDP_STATS
+ ++stats.udp.chkerr;
+ ++stats.udp.drop;
+#endif /* UDP_STATS */
+ pbuf_free(p);
+ goto end;
+ }
+ } else {
+ if(udphdr->chksum != 0) {
+ if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_UDP, p->tot_len) != 0) {
+ DEBUGF(UDP_DEBUG, ("udp_input: UDP datagram discarded due to failing checksum\n"));
+
+#ifdef UDP_STATS
+ ++stats.udp.chkerr;
+ ++stats.udp.drop;
+#endif /* UDP_STATS */
+ pbuf_free(p);
+ goto end;
+ }
+ }
+ }
+ pbuf_header(p, -UDP_HLEN);
+ if(pcb != NULL) {
+ pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
+ } else {
+ DEBUGF(UDP_DEBUG, ("udp_input: not for us.\n"));
+
+ /* No match was found, send ICMP destination port unreachable unless
+ destination address was broadcast/multicast. */
+
+ if(!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) &&
+ !ip_addr_ismulticast(&iphdr->dest)) {
+
+ /* deconvert from host to network byte order */
+ udphdr->src = htons(udphdr->src);
+ udphdr->dest = htons(udphdr->dest);
+
+ /* adjust pbuf pointer */
+ p->payload = iphdr;
+ icmp_dest_unreach(p, ICMP_DUR_PORT);
+ }
+#ifdef UDP_STATS
+ ++stats.udp.proterr;
+ ++stats.udp.drop;
+#endif /* UDP_STATS */
+ pbuf_free(p);
+ }
+ } else {
+ pbuf_free(p);
+ }
+ end:
+
+ PERF_STOP("udp_input");
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+udp_send(struct udp_pcb *pcb, struct pbuf *p)
+{
+ struct udp_hdr *udphdr;
+ struct netif *netif;
+ struct ip_addr *src_ip;
+ err_t err;
+ struct pbuf *hdr;
+
+ /* hdr will point to the UDP header pbuf if an extra header pbuf has
+ to be allocated. */
+ hdr = NULL;
+
+ if(pbuf_header(p, UDP_HLEN)) {
+ hdr = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
+ if(hdr == NULL) {
+ return ERR_MEM;
+ }
+ pbuf_chain(hdr, p);
+ p = hdr;
+ }
+
+ udphdr = p->payload;
+ udphdr->src = htons(pcb->local_port);
+ udphdr->dest = htons(pcb->remote_port);
+ udphdr->chksum = 0x0000;
+
+ if((netif = ip_route(&(pcb->remote_ip))) == NULL) {
+ DEBUGF(UDP_DEBUG, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
+#ifdef UDP_STATS
+ ++stats.udp.rterr;
+#endif /* UDP_STATS */
+ return ERR_RTE;
+ }
+
+ if(ip_addr_isany(&pcb->local_ip)) {
+ src_ip = &(netif->ip_addr);
+ } else {
+ src_ip = &(pcb->local_ip);
+ }
+
+ DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %d\n", p->tot_len));
+
+ if(pcb->flags & UDP_FLAGS_UDPLITE) {
+ udphdr->len = htons(pcb->chksum_len);
+ /* calculate checksum */
+ udphdr->chksum = inet_chksum_pseudo(p, src_ip, &(pcb->remote_ip),
+ IP_PROTO_UDP, pcb->chksum_len);
+ if(udphdr->chksum == 0x0000) {
+ udphdr->chksum = 0xffff;
+ }
+ err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
+ } else {
+ udphdr->len = htons(p->tot_len);
+ /* calculate checksum */
+ if((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
+ udphdr->chksum = inet_chksum_pseudo(p, src_ip, &pcb->remote_ip,
+ IP_PROTO_UDP, p->tot_len);
+ if(udphdr->chksum == 0x0000) {
+ udphdr->chksum = 0xffff;
+ }
+ }
+ err = ip_output_if(p, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);
+ }
+
+ if(hdr != NULL) {
+ pbuf_dechain(hdr);
+ pbuf_free(hdr);
+ }
+
+#ifdef UDP_STATS
+ ++stats.udp.xmit;
+#endif /* UDP_STATS */
+ return err;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+{
+ struct udp_pcb *ipcb;
+ ip_addr_set(&pcb->local_ip, ipaddr);
+ pcb->local_port = port;
+
+ /* Insert UDP PCB into the list of active UDP PCBs. */
+ for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
+ if(pcb == ipcb) {
+ /* Already on the list, just return. */
+ return ERR_OK;
+ }
+ }
+ /* We need to place the PCB on the list. */
+ pcb->next = udp_pcbs;
+ udp_pcbs = pcb;
+
+ DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %d\n", port));
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+{
+ struct udp_pcb *ipcb;
+ ip_addr_set(&pcb->remote_ip, ipaddr);
+ pcb->remote_port = port;
+
+ /* Insert UDP PCB into the list of active UDP PCBs. */
+ for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
+ if(pcb == ipcb) {
+ /* Already on the list, just return. */
+ return ERR_OK;
+ }
+ }
+ /* We need to place the PCB on the list. */
+ pcb->next = udp_pcbs;
+ udp_pcbs = pcb;
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+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)
+{
+ pcb->recv = recv;
+ pcb->recv_arg = recv_arg;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+udp_remove(struct udp_pcb *pcb)
+{
+ struct udp_pcb *pcb2;
+
+ if(udp_pcbs == pcb) {
+ udp_pcbs = udp_pcbs->next;
+ } else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
+ if(pcb2->next != NULL && pcb2->next == pcb) {
+ pcb2->next = pcb->next;
+ }
+ }
+
+ memp_free(MEMP_UDP_PCB, pcb);
+}
+/*-----------------------------------------------------------------------------------*/
+struct udp_pcb *
+udp_new(void) {
+ struct udp_pcb *pcb;
+ pcb = memp_malloc(MEMP_UDP_PCB);
+ if(pcb != NULL) {
+ bzero(pcb, sizeof(struct udp_pcb));
+ return pcb;
+ }
+ return NULL;
+
+}
+/*-----------------------------------------------------------------------------------*/
+#if UDP_DEBUG
+int
+udp_debug_print(struct udp_hdr *udphdr)
+{
+ DEBUGF(UDP_DEBUG, ("UDP header:\n"));
+ DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(UDP_DEBUG, ("| %5d | %5d | (src port, dest port)\n",
+ ntohs(udphdr->src), ntohs(udphdr->dest)));
+ DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
+ DEBUGF(UDP_DEBUG, ("| %5d | 0x%04x | (len, chksum)\n",
+ ntohs(udphdr->len), ntohs(udphdr->chksum)));
+ DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
+ return 0;
+}
+#endif /* UDP_DEBUG */
+/*-----------------------------------------------------------------------------------*/
+#endif /* LWIP_UDP */
+
+
+
+
+
+
+
+
+
diff --git a/src/include/ipv4/lwip/icmp.h b/src/include/ipv4/lwip/icmp.h
new file mode 100644
index 0000000..b096b3c
--- /dev/null
+++ b/src/include/ipv4/lwip/icmp.h
@@ -0,0 +1,105 @@
+/*
+ * 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 __LWIP_ICMP_H__
+#define __LWIP_ICMP_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+
+#include "lwip/netif.h"
+
+#define ICMP_ER 0 /* echo reply */
+#define ICMP_DUR 3 /* destination unreachable */
+#define ICMP_SQ 4 /* source quench */
+#define ICMP_RD 5 /* redirect */
+#define ICMP_ECHO 8 /* echo */
+#define ICMP_TE 11 /* time exceeded */
+#define ICMP_PP 12 /* parameter problem */
+#define ICMP_TS 13 /* timestamp */
+#define ICMP_TSR 14 /* timestamp reply */
+#define ICMP_IRQ 15 /* information request */
+#define ICMP_IR 16 /* information reply */
+
+enum icmp_dur_type {
+ ICMP_DUR_NET = 0, /* net unreachable */
+ ICMP_DUR_HOST = 1, /* host unreachable */
+ ICMP_DUR_PROTO = 2, /* protocol unreachable */
+ ICMP_DUR_PORT = 3, /* port unreachable */
+ ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
+ ICMP_DUR_SR = 5 /* source route failed */
+};
+
+enum icmp_te_type {
+ ICMP_TE_TTL = 0, /* time to live exceeded in transit */
+ ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
+};
+
+void icmp_input(struct pbuf *p, struct netif *inp);
+
+void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
+void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
+
+PACK_STRUCT_BEGIN
+struct icmp_echo_hdr {
+ PACK_STRUCT_FIELD(u16_t _type_code);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u16_t id);
+ PACK_STRUCT_FIELD(u16_t seqno);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+struct icmp_dur_hdr {
+ PACK_STRUCT_FIELD(u16_t _type_code);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u32_t unused);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+struct icmp_te_hdr {
+ PACK_STRUCT_FIELD(u16_t _type_code);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u32_t unused);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define ICMPH_TYPE(hdr) (NTOHS((hdr)->_type_code) >> 8)
+#define ICMPH_CODE(hdr) (NTOHS((hdr)->_type_code) & 0xff)
+
+#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = HTONS(ICMPH_CODE(hdr) | ((type) << 8)))
+#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = HTONS((code) | (ICMPH_TYPE(hdr) << 8)))
+
+#endif /* __LWIP_ICMP_H__ */
+
diff --git a/src/include/ipv4/lwip/inet.h b/src/include/ipv4/lwip/inet.h
new file mode 100644
index 0000000..19f5fb4
--- /dev/null
+++ b/src/include/ipv4/lwip/inet.h
@@ -0,0 +1,105 @@
+/*
+ * 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 __LWIP_INET_H__
+#define __LWIP_INET_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+
+u16_t inet_chksum(void *dataptr, u16_t len);
+u16_t inet_chksum_pbuf(struct pbuf *p);
+u16_t inet_chksum_pseudo(struct pbuf *p,
+ struct ip_addr *src, struct ip_addr *dest,
+ u8_t proto, u16_t proto_len);
+
+#ifdef HTONS
+#undef HTONS
+#endif /* HTONS */
+#ifdef NTOHS
+#undef NTOHS
+#endif /* NTOHS */
+#ifdef HTONL
+#undef HTONL
+#endif /* HTONL */
+#ifdef NTOHL
+#undef NTOHL
+#endif /* NTOHL */
+
+#ifdef htons
+#undef htons
+#endif /* htons */
+#ifdef htonl
+#undef htonl
+#endif /* htonl */
+#ifdef ntohs
+#undef ntohs
+#endif /* ntohs */
+#ifdef ntohl
+#undef ntohl
+#endif /* ntohl */
+
+
+
+#ifndef HTONS
+# if BYTE_ORDER == BIG_ENDIAN
+# define HTONS(n) (n)
+# else /* BYTE_ORDER == BIG_ENDIAN */
+# define HTONS(n) (((((u16_t)(n) & 0xff)) << 8) | (((u16_t)(n) & 0xff00) >> 8))
+# endif /* BYTE_ORDER == BIG_ENDIAN */
+#endif /* HTONS */
+
+#define htons HTONS
+#define NTOHS HTONS
+#define ntohs htons
+
+
+#ifndef HTONL
+# if BYTE_ORDER == BIG_ENDIAN
+# define HTONL(n) (n)
+# else /* BYTE_ORDER == BIG_ENDIAN */
+# define HTONL(n) (((((u32_t)(n) & 0xff)) << 24) | \
+ ((((u32_t)(n) & 0xff00)) << 8) | \
+ ((((u32_t)(n) & 0xff0000)) >> 8) | \
+ ((((u32_t)(n) & 0xff000000)) >> 24))
+# endif /* BYTE_ORDER == BIG_ENDIAN */
+#endif /* HTONL */
+
+
+#define htonl HTONL
+#define NTOHL HTONL
+#define ntohl htonl
+
+#endif /* __LWIP_INET_H__ */
+
diff --git a/src/include/ipv4/lwip/ip.h b/src/include/ipv4/lwip/ip.h
new file mode 100644
index 0000000..e8257c9
--- /dev/null
+++ b/src/include/ipv4/lwip/ip.h
@@ -0,0 +1,119 @@
+/*
+ * 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 __LWIP_IP_H__
+#define __LWIP_IP_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/def.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+#include "lwip/netif.h"
+
+#include "lwip/err.h"
+
+void ip_init(void);
+u8_t ip_lookup(void *header, struct netif *inp);
+struct netif *ip_route(struct ip_addr *dest);
+err_t ip_input(struct pbuf *p, struct netif *inp);
+err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl, u8_t proto);
+err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ u8_t ttl, u8_t proto,
+ struct netif *netif);
+
+#define IP_HLEN 20
+
+#define IP_PROTO_ICMP 1
+#define IP_PROTO_UDP 17
+#define IP_PROTO_UDPLITE 170
+#define IP_PROTO_TCP 6
+
+/* This is passed as the destination address to ip_output_if (not
+ to ip_output), meaning that an IP header already is constructed
+ in the pbuf. This is used when TCP retransmits. */
+#ifdef IP_HDRINCL
+#undef IP_HDRINCL
+#endif /* IP_HDRINCL */
+#define IP_HDRINCL NULL
+
+PACK_STRUCT_BEGIN
+struct ip_hdr {
+ /* version / header length / type of service */
+ PACK_STRUCT_FIELD(u16_t _v_hl_tos);
+ /* total length */
+ PACK_STRUCT_FIELD(u16_t _len);
+ /* identification */
+ PACK_STRUCT_FIELD(u16_t _id);
+ /* fragment offset field */
+ PACK_STRUCT_FIELD(u16_t _offset);
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ /* time to live / protocol*/
+ PACK_STRUCT_FIELD(u16_t _ttl_proto);
+ /* checksum */
+ PACK_STRUCT_FIELD(u16_t _chksum);
+ /* source and destination IP addresses */
+ PACK_STRUCT_FIELD(struct ip_addr src);
+ PACK_STRUCT_FIELD(struct ip_addr dest);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define IPH_V(hdr) (NTOHS((hdr)->_v_hl_tos) >> 12)
+#define IPH_HL(hdr) ((NTOHS((hdr)->_v_hl_tos) >> 8) & 0x0f)
+#define IPH_TOS(hdr) HTONS((NTOHS((hdr)->_v_hl_tos) & 0xff))
+#define IPH_LEN(hdr) ((hdr)->_len)
+#define IPH_ID(hdr) ((hdr)->_id)
+#define IPH_OFFSET(hdr) ((hdr)->_offset)
+#define IPH_TTL(hdr) (NTOHS((hdr)->_ttl_proto) >> 8)
+#define IPH_PROTO(hdr) (NTOHS((hdr)->_ttl_proto) & 0xff)
+#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
+
+#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = HTONS(((v) << 12) | ((hl) << 8) | (tos))
+#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
+#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
+#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
+#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = HTONS(IPH_PROTO(hdr) | ((ttl) << 8))
+#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = HTONS((proto) | (IPH_TTL(hdr) << 8))
+#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
+
+
+
+#if IP_DEBUG
+void ip_debug_print(struct pbuf *p);
+#endif /* IP_DEBUG */
+
+#endif /* __LWIP_IP_H__ */
+
+
diff --git a/src/include/ipv4/lwip/ip_addr.h b/src/include/ipv4/lwip/ip_addr.h
new file mode 100644
index 0000000..cca1cda
--- /dev/null
+++ b/src/include/ipv4/lwip/ip_addr.h
@@ -0,0 +1,89 @@
+/*
+ * 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 __LWIP_IP_ADDR_H__
+#define __LWIP_IP_ADDR_H__
+
+#include "lwip/arch.h"
+
+#define IP_ADDR_ANY 0
+
+#define IP_ADDR_BROADCAST (&ip_addr_broadcast)
+
+PACK_STRUCT_BEGIN
+struct ip_addr {
+ PACK_STRUCT_FIELD(u32_t addr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+extern struct ip_addr ip_addr_broadcast;
+
+#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
+ ((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
+
+#define ip_addr_set(dest, src) (dest)->addr = \
+ ((src) == IP_ADDR_ANY? IP_ADDR_ANY:\
+ ((struct ip_addr *)src)->addr)
+#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
+ (mask)->addr) == \
+ ((addr2)->addr & \
+ (mask)->addr))
+#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
+
+#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
+
+#define ip_addr_isbroadcast(addr1, mask) (((((addr1)->addr) & ~((mask)->addr)) == \
+ (0xffffffff & ~((mask)->addr))) || \
+ ((addr1)->addr == 0xffffffff) || \
+ ((addr1)->addr == 0x00000000))
+
+
+#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
+
+
+#define ip_addr_debug_print(ipaddr) DEBUGF(LWIP_DEBUG, ("%d.%d.%d.%d", \
+ (u8_t)(ntohl((ipaddr)->addr) >> 24) & 0xff, \
+ (u8_t)(ntohl((ipaddr)->addr) >> 16) & 0xff, \
+ (u8_t)(ntohl((ipaddr)->addr) >> 8) & 0xff, \
+ (u8_t)ntohl((ipaddr)->addr) & 0xff))
+
+
+#define ip4_addr1(ipaddr) ((u8_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
+#define ip4_addr2(ipaddr) ((u8_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
+#define ip4_addr3(ipaddr) ((u8_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
+#define ip4_addr4(ipaddr) ((u8_t)(ntohl((ipaddr)->addr)) & 0xff)
+#endif /* __LWIP_IP_ADDR_H__ */
+
+
+
+
+
+
diff --git a/src/include/ipv6/lwip/icmp.h b/src/include/ipv6/lwip/icmp.h
new file mode 100644
index 0000000..09fa12a
--- /dev/null
+++ b/src/include/ipv6/lwip/icmp.h
@@ -0,0 +1,90 @@
+/*
+ * 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 __LWIP_ICMP_H__
+#define __LWIP_ICMP_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+
+#include "lwip/netif.h"
+
+#define ICMP6_DUR 1
+#define ICMP6_TE 3
+#define ICMP6_ECHO 128 /* echo */
+#define ICMP6_ER 129 /* echo reply */
+
+
+enum icmp_dur_type {
+ ICMP_DUR_NET = 0, /* net unreachable */
+ ICMP_DUR_HOST = 1, /* host unreachable */
+ ICMP_DUR_PROTO = 2, /* protocol unreachable */
+ ICMP_DUR_PORT = 3, /* port unreachable */
+ ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
+ ICMP_DUR_SR = 5 /* source route failed */
+};
+
+enum icmp_te_type {
+ ICMP_TE_TTL = 0, /* time to live exceeded in transit */
+ ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
+};
+
+void icmp_input(struct pbuf *p, struct netif *inp);
+
+void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
+void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
+
+struct icmp_echo_hdr {
+ u8_t type;
+ u8_t icode;
+ u16_t chksum;
+ u16_t id;
+ u16_t seqno;
+};
+
+struct icmp_dur_hdr {
+ u8_t type;
+ u8_t icode;
+ u16_t chksum;
+ u32_t unused;
+};
+
+struct icmp_te_hdr {
+ u8_t type;
+ u8_t icode;
+ u16_t chksum;
+ u32_t unused;
+};
+
+#endif /* __LWIP_ICMP_H__ */
+
diff --git a/src/include/ipv6/lwip/inet.h b/src/include/ipv6/lwip/inet.h
new file mode 100644
index 0000000..65c1137
--- /dev/null
+++ b/src/include/ipv6/lwip/inet.h
@@ -0,0 +1,60 @@
+/*
+ * 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 __LWIP_INET_H__
+#define __LWIP_INET_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+
+u16_t inet_chksum(void *data, u16_t len);
+u16_t inet_chksum_pbuf(struct pbuf *p);
+u16_t inet_chksum_pseudo(struct pbuf *p,
+ struct ip_addr *src, struct ip_addr *dest,
+ u8_t proto, u32_t proto_len);
+
+
+#ifndef _MACHINE_ENDIAN_H_
+#ifndef _NETINET_IN_H
+#ifndef _LINUX_BYTEORDER_GENERIC_H
+u16_t htons(u16_t n);
+u16_t ntohs(u16_t n);
+u32_t htonl(u32_t n);
+u32_t ntohl(u32_t n);
+#endif /* _LINUX_BYTEORDER_GENERIC_H */
+#endif /* _NETINET_IN_H */
+#endif /* _MACHINE_ENDIAN_H_ */
+
+#endif /* __LWIP_INET_H__ */
+
diff --git a/src/include/ipv6/lwip/ip.h b/src/include/ipv6/lwip/ip.h
new file mode 100644
index 0000000..2ffc2a9
--- /dev/null
+++ b/src/include/ipv6/lwip/ip.h
@@ -0,0 +1,96 @@
+/*
+ * 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 __LWIP_IP_H__
+#define __LWIP_IP_H__
+
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+
+#include "lwip/err.h"
+
+#define IP_HLEN 40
+
+#define IP_PROTO_ICMP 58
+#define IP_PROTO_UDP 17
+#define IP_PROTO_UDPLITE 170
+#define IP_PROTO_TCP 6
+
+/* This is passed as the destination address to ip_output_if (not
+ to ip_output), meaning that an IP header already is constructed
+ in the pbuf. This is used when TCP retransmits. */
+#ifdef IP_HDRINCL
+#undef IP_HDRINCL
+#endif /* IP_HDRINCL */
+#define IP_HDRINCL NULL
+
+
+/* The IPv6 header. */
+struct ip_hdr {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u8_t tclass1:4, v:4;
+ u8_t flow1:4, tclass2:4;
+#else
+ u8_t v:4, tclass1:4;
+ u8_t tclass2:8, flow1:4;
+#endif
+ u16_t flow2;
+ u16_t len; /* payload length */
+ u8_t nexthdr; /* next header */
+ u8_t hoplim; /* hop limit (TTL) */
+ struct ip_addr src, dest; /* source and destination IP addresses */
+};
+
+void ip_init(void);
+
+#include "lwip/netif.h"
+
+struct netif *ip_route(struct ip_addr *dest);
+
+void ip_input(struct pbuf *p, struct netif *inp);
+
+/* source and destination addresses in network byte order, please */
+err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ unsigned char ttl, unsigned char proto);
+
+err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ unsigned char ttl, unsigned char proto,
+ struct netif *netif);
+
+#if IP_DEBUG
+void ip_debug_print(struct pbuf *p);
+#endif /* IP_DEBUG */
+
+#endif /* __LWIP_IP_H__ */
+
+
diff --git a/src/include/ipv6/lwip/ip_addr.h b/src/include/ipv6/lwip/ip_addr.h
new file mode 100644
index 0000000..5e971f5
--- /dev/null
+++ b/src/include/ipv6/lwip/ip_addr.h
@@ -0,0 +1,59 @@
+/*
+ * 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 __LWIP_IP_ADDR_H__
+#define __LWIP_IP_ADDR_H__
+
+#include "lwip/arch.h"
+
+#define IP_ADDR_ANY 0
+
+struct ip_addr {
+ u32_t addr[4];
+};
+
+#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \
+ (ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \
+ (ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
+ (ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
+
+int ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
+ struct ip_addr *mask);
+int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
+void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
+int ip_addr_isany(struct ip_addr *addr);
+
+
+#if IP_DEBUG
+void ip_addr_debug_print(struct ip_addr *addr);
+#endif /* IP_DEBUG */
+
+#endif /* __LWIP_IP_ADDR_H__ */
diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h
new file mode 100644
index 0000000..9b01cad
--- /dev/null
+++ b/src/include/lwip/api.h
@@ -0,0 +1,137 @@
+/*
+ * 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 __LWIP_API_H__
+#define __LWIP_API_H__
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include "lwip/ip.h"
+
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "lwip/err.h"
+
+#define NETCONN_NOCOPY 0x00
+#define NETCONN_COPY 0x01
+
+enum netconn_type {
+ NETCONN_TCP,
+ NETCONN_UDP,
+ NETCONN_UDPLITE,
+ NETCONN_UDPNOCHKSUM
+};
+
+enum netconn_state {
+ NETCONN_NONE,
+ NETCONN_WRITE,
+ NETCONN_ACCEPT,
+ NETCONN_RECV,
+ NETCONN_CONNECT,
+ NETCONN_CLOSE
+};
+
+struct netbuf {
+ struct pbuf *p, *ptr;
+ struct ip_addr *fromaddr;
+ u16_t fromport;
+ err_t err;
+};
+
+struct netconn {
+ enum netconn_type type;
+ enum netconn_state state;
+ union {
+ struct tcp_pcb *tcp;
+ struct udp_pcb *udp;
+ } pcb;
+ err_t err;
+ sys_mbox_t mbox;
+ sys_mbox_t recvmbox;
+ sys_mbox_t acceptmbox;
+ sys_sem_t sem;
+};
+
+/* Network buffer functions: */
+struct netbuf * netbuf_new (void);
+void netbuf_delete (struct netbuf *buf);
+void * netbuf_alloc (struct netbuf *buf, u16_t size);
+void netbuf_free (struct netbuf *buf);
+void netbuf_ref (struct netbuf *buf,
+ void *dataptr, u16_t size);
+void netbuf_chain (struct netbuf *head,
+ struct netbuf *tail);
+
+u16_t netbuf_len (struct netbuf *buf);
+err_t netbuf_data (struct netbuf *buf,
+ void **dataptr, u16_t *len);
+s8_t netbuf_next (struct netbuf *buf);
+void netbuf_first (struct netbuf *buf);
+
+void netbuf_copy (struct netbuf *buf,
+ void *dataptr, u16_t len);
+struct ip_addr * netbuf_fromaddr (struct netbuf *buf);
+u16_t netbuf_fromport (struct netbuf *buf);
+
+/* Network connection functions: */
+struct netconn * netconn_new (enum netconn_type type);
+err_t netconn_delete (struct netconn *conn);
+enum netconn_type netconn_type (struct netconn *conn);
+err_t netconn_peer (struct netconn *conn,
+ struct ip_addr **addr,
+ u16_t *port);
+err_t netconn_addr (struct netconn *conn,
+ struct ip_addr **addr,
+ u16_t *port);
+err_t netconn_bind (struct netconn *conn,
+ struct ip_addr *addr,
+ u16_t port);
+err_t netconn_connect (struct netconn *conn,
+ struct ip_addr *addr,
+ u16_t port);
+err_t netconn_listen (struct netconn *conn);
+struct netconn * netconn_accept (struct netconn *conn);
+struct netbuf * netconn_recv (struct netconn *conn);
+err_t netconn_send (struct netconn *conn,
+ struct netbuf *buf);
+err_t netconn_write (struct netconn *conn,
+ void *dataptr, u16_t size,
+ u8_t copy);
+err_t netconn_close (struct netconn *conn);
+
+err_t netconn_err (struct netconn *conn);
+
+#endif /* __LWIP_API_H__ */
+
+
diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h
new file mode 100644
index 0000000..ae94161
--- /dev/null
+++ b/src/include/lwip/api_msg.h
@@ -0,0 +1,93 @@
+/*
+ * 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 __LWIP_API_MSG_H__
+#define __LWIP_API_MSG_H__
+
+#include "lwip/opt.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include "lwip/ip.h"
+
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "lwip/api.h"
+
+enum api_msg_type {
+ API_MSG_NEWCONN,
+ API_MSG_DELCONN,
+
+ API_MSG_BIND,
+ API_MSG_CONNECT,
+
+ API_MSG_LISTEN,
+ API_MSG_ACCEPT,
+
+ API_MSG_SEND,
+ API_MSG_RECV,
+ API_MSG_WRITE,
+
+ API_MSG_CLOSE,
+
+ API_MSG_MAX
+};
+
+struct api_msg_msg {
+ struct netconn *conn;
+ enum netconn_type conntype;
+ union {
+ struct pbuf *p;
+ struct {
+ struct ip_addr *ipaddr;
+ u16_t port;
+ } bc;
+ struct {
+ void *dataptr;
+ u16_t len;
+ unsigned char copy;
+ } w;
+ sys_mbox_t mbox;
+ u16_t len;
+ } msg;
+};
+
+struct api_msg {
+ enum api_msg_type type;
+ struct api_msg_msg msg;
+};
+
+void api_msg_input(struct api_msg *msg);
+void api_msg_post(struct api_msg *msg);
+
+#endif /* __LWIP_API_MSG_H__ */
+
diff --git a/src/include/lwip/arch.h b/src/include/lwip/arch.h
new file mode 100644
index 0000000..21b3f4b
--- /dev/null
+++ b/src/include/lwip/arch.h
@@ -0,0 +1,58 @@
+/*
+ * 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 __LWIP_ARCH_H__
+#define __LWIP_ARCH_H__
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#include "arch/cpu.h"
+#include "arch/cc.h"
+
+#ifndef PACK_STRUCT_BEGIN
+#define PACK_STRUCT_BEGIN
+#endif /* PACK_STRUCT_BEGIN */
+
+#ifndef PACK_STRUCT_END
+#define PACK_STRUCT_END
+#endif /* PACK_STRUCT_END */
+
+#ifndef PACK_STRUCT_FIELD
+#define PACK_STRUCT_FIELD(x) x
+#endif /* PACK_STRUCT_FIELD */
+
+#endif /* __LWIP_ARCH_H__ */
diff --git a/src/include/lwip/debug.h b/src/include/lwip/debug.h
new file mode 100644
index 0000000..0a44409
--- /dev/null
+++ b/src/include/lwip/debug.h
@@ -0,0 +1,136 @@
+/*
+ * 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 __LWIP_DEBUG_H__
+#define __LWIP_DEBUG_H__
+
+#ifdef LWIP_DEBUG
+
+#define ASSERT(x,y) if(!(y)) {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); fflush(NULL); abort();}
+
+/* These defines control the amount of debugging output: */
+#define MEM_TRACKING
+
+#define DEMO_DEBUG 1
+
+#define ETHARP_DEBUG 1
+
+#define NETIF_DEBUG 0
+#define PBUF_DEBUG 0
+#define DELIF_DEBUG 0
+#define DROPIF_DEBUG 0
+#define TUNIF_DEBUG 0
+#define UNIXIF_DEBUG 0
+#define TAPIF_DEBUG 1
+
+#define API_LIB_DEBUG 0
+#define API_MSG_DEBUG 0
+#define SOCKETS_DEBUG 1
+#define ICMP_DEBUG 0
+#define INET_DEBUG 0
+#define IP_DEBUG 1
+#define IP_REASS_DEBUG 1
+#define MEM_DEBUG 0
+#define MEMP_DEBUG 0
+#define SYS_DEBUG 0
+#define TCP_DEBUG 0
+#define TCP_INPUT_DEBUG 0
+#define TCP_FR_DEBUG 0
+#define TCP_RTO_DEBUG 0
+#define TCP_REXMIT_DEBUG 0
+#define TCP_CWND_DEBUG 0
+#define TCP_WND_DEBUG 0
+#define TCP_OUTPUT_DEBUG 0
+#define TCP_RST_DEBUG 0
+#define TCP_QLEN_DEBUG 0
+#define UDP_DEBUG 0
+#define TCPIP_DEBUG 0
+#define TCPDUMP_DEBUG 0
+#define DHCP_DEBUG 1
+
+#include <stdio.h>
+#define DEBUGF(debug, x) do { if(debug){ printf x; } } while(0)
+
+
+#else /* LWIP_DEBUG */
+
+/* DEBUG is not defined, so we define null macros for ASSERT and DEBUGF */
+
+#define ASSERT(x,y)
+#define DEBUGF(debug, x)
+
+/* And we define those to be zero: */
+
+#define DEMO_DEBUG 0
+#define ETHARP_DEBUG 0
+#define NETIF_DEBUG 0
+#define PBUF_DEBUG 0
+#define DELIF_DEBUG 0
+#define DROPIF_DEBUG 0
+#define TUNIF_DEBUG 0
+#define UNIXIF_DEBUG 0
+#define TAPIF_DEBUG 0
+#define API_LIB_DEBUG 0
+#define API_MSG_DEBUG 0
+#define SOCKETS_DEBUG 0
+#define ICMP_DEBUG 0
+#define INET_DEBUG 0
+#define IP_DEBUG 0
+#define IP_REASS_DEBUG 0
+#define MEM_DEBUG 0
+#define MEMP_DEBUG 0
+#define SYS_DEBUG 0
+#define TCP_DEBUG 0
+#define TCP_INPUT_DEBUG 0
+#define TCP_FR_DEBUG 0
+#define TCP_RTO_DEBUG 0
+#define TCP_REXMIT_DEBUG 0
+#define TCP_CWND_DEBUG 0
+#define TCP_WND_DEBUG 0
+#define TCP_OUTPUT_DEBUG 0
+#define TCP_RST_DEBUG 0
+#define TCP_QLEN_DEBUG 0
+#define UDP_DEBUG 0
+#define TCPIP_DEBUG 0
+#define TCPDUMP_DEBUG 0
+#define DHCP_DEBUG 0
+
+#endif /* LWIP_DEBUG */
+
+
+#endif /* __LWIP_DEBUG_H__ */
+
+
+
+
+
+
diff --git a/src/include/lwip/def.h b/src/include/lwip/def.h
new file mode 100644
index 0000000..55d1734
--- /dev/null
+++ b/src/include/lwip/def.h
@@ -0,0 +1,44 @@
+/*
+ * 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 __LWIP_DEF_H__
+#define __LWIP_DEF_H__
+
+#define UMAX(a, b) ((a) > (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#include "arch/lib.h"
+
+#endif /* __LWIP_DEF_H__ */
+
diff --git a/src/include/lwip/err.h b/src/include/lwip/err.h
new file mode 100644
index 0000000..bed85fe
--- /dev/null
+++ b/src/include/lwip/err.h
@@ -0,0 +1,68 @@
+/*
+ * 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 __LWIP_ERR_H__
+#define __LWIP_ERR_H__
+
+#include "lwip/debug.h"
+
+#include "arch/cc.h"
+
+typedef s8_t err_t;
+
+/* Definitions for error constants. */
+
+#define ERR_OK 0 /* No error, everything OK. */
+#define ERR_MEM -1 /* Out of memory error. */
+#define ERR_BUF -2 /* Buffer error. */
+
+
+#define ERR_ABRT -3 /* Connection aborted. */
+#define ERR_RST -4 /* Connection reset. */
+#define ERR_CLSD -5 /* Connection closed. */
+#define ERR_CONN -6 /* Not connected. */
+
+#define ERR_VAL -7 /* Illegal value. */
+
+#define ERR_ARG -8 /* Illegal argument. */
+
+#define ERR_RTE -9 /* Routing problem. */
+
+#define ERR_USE -10 /* Address in use. */
+
+
+
+#ifdef LWIP_DEBUG
+extern char *lwip_strerr(err_t err);
+#else
+#define lwip_strerr(x) ""
+#endif /* LWIP_DEBUG */
+#endif /* __LWIP_ERR_H__ */
diff --git a/src/include/lwip/event.h b/src/include/lwip/event.h
new file mode 100644
index 0000000..677cafc
--- /dev/null
+++ b/src/include/lwip/event.h
@@ -0,0 +1,29 @@
+#ifndef __LWIP_EVENT_H__
+#define __LWIP_EVENT_H__
+
+#include "lwip/opt.h"
+
+#if LWIP_EVENT_API
+
+#include "lwip/pbuf.h"
+
+enum lwip_event {
+ LWIP_EVENT_ACCEPT,
+ LWIP_EVENT_SENT,
+ LWIP_EVENT_RECV,
+ LWIP_EVENT_CONNECTED,
+ LWIP_EVENT_POLL,
+ LWIP_EVENT_ERR
+};
+
+struct tcp_pcb;
+
+err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
+ enum lwip_event,
+ struct pbuf *p,
+ u16_t size,
+ err_t err);
+
+#endif /* LWIP_EVENT_API */
+
+#endif /* __LWIP_EVENT_H__ */
diff --git a/src/include/lwip/list.h b/src/include/lwip/list.h
new file mode 100644
index 0000000..14c14fc
--- /dev/null
+++ b/src/include/lwip/list.h
@@ -0,0 +1,47 @@
+/*
+ * 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 __LWIP_LIST_H__
+#define __LWIP_LIST_H__
+
+struct list;
+
+struct list *list_new(int size);
+int list_push(struct list *list, void *elem);
+void *list_pop(struct list *list);
+int list_remove(struct list *list, void *elem);
+void *list_first(struct list *list);
+int list_elems(struct list *list);
+void list_delete(struct list *list);
+
+void list_map(struct list *list, void (* func)(void *arg));
+
+#endif /* __LWIP_LIST_H__ */
diff --git a/src/include/lwip/mem.h b/src/include/lwip/mem.h
new file mode 100644
index 0000000..61b9610
--- /dev/null
+++ b/src/include/lwip/mem.h
@@ -0,0 +1,60 @@
+/*
+ * 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 __LWIP_MEM_H__
+#define __LWIP_MEM_H__
+
+#include "lwip/debug.h"
+#include "lwip/opt.h"
+#include "lwip/arch.h"
+
+#if MEM_SIZE > 64000l
+typedef u32_t mem_size_t;
+#else
+typedef u16_t mem_size_t;
+#endif /* MEM_SIZE > 64000 */
+
+
+void mem_init(void);
+
+void *mem_malloc(mem_size_t size);
+void mem_free(void *mem);
+void *mem_realloc(void *mem, mem_size_t size);
+void *mem_reallocm(void *mem, mem_size_t size);
+
+#define MEM_ALIGN_SIZE(size) (size + \
+ ((((size) % MEM_ALIGNMENT) == 0)? 0 : \
+ (MEM_ALIGNMENT - ((size) % MEM_ALIGNMENT))))
+
+#define MEM_ALIGN(addr) (void *)MEM_ALIGN_SIZE((mem_ptr_t)addr)
+
+#endif /* __LWIP_MEM_H__ */
+
diff --git a/src/include/lwip/memp.h b/src/include/lwip/memp.h
new file mode 100644
index 0000000..5bd7832
--- /dev/null
+++ b/src/include/lwip/memp.h
@@ -0,0 +1,67 @@
+/*
+ * 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 __LWIP_MEMP_H__
+#define __LWIP_MEMP_H__
+
+#include "lwip/debug.h"
+#include "arch/cc.h"
+#include "lwipopts.h"
+
+typedef enum {
+ MEMP_PBUF,
+ MEMP_UDP_PCB,
+ MEMP_TCP_PCB,
+ MEMP_TCP_PCB_LISTEN,
+ MEMP_TCP_SEG,
+
+ MEMP_NETBUF,
+ MEMP_NETCONN,
+ MEMP_API_MSG,
+ MEMP_TCPIP_MSG,
+
+ MEMP_SYS_TIMEOUT,
+
+ MEMP_MAX
+} memp_t;
+
+void memp_init(void);
+
+void *memp_malloc(memp_t type);
+void *memp_realloc(memp_t fromtype, memp_t totype, void *mem);
+void memp_free(memp_t type, void *mem);
+
+void *memp_mallocp(memp_t type);
+void memp_freep(memp_t type, void *mem);
+
+#endif /* __LWIP_MEMP_H__ */
+
diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h
new file mode 100644
index 0000000..579b9aa
--- /dev/null
+++ b/src/include/lwip/netif.h
@@ -0,0 +1,97 @@
+/*
+ * 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 __LWIP_NETIF_H__
+#define __LWIP_NETIF_H__
+
+#include "lwip/opt.h"
+
+#include "lwip/err.h"
+
+#include "lwip/ip_addr.h"
+
+#include "lwip/inet.h"
+#include "lwip/pbuf.h"
+
+
+struct netif {
+ struct netif *next;
+ u8_t num;
+ struct ip_addr ip_addr;
+ struct ip_addr netmask; /* netmask in network byte order */
+ struct ip_addr gw;
+ char hwaddr[6];
+
+ /* This function is called by the network device driver
+ when it wants to pass a packet to the TCP/IP stack. */
+ err_t (* input)(struct pbuf *p, struct netif *inp);
+
+ /* The following two fields should be filled in by the
+ initialization function for the device driver. */
+
+ char name[2];
+ /* This function is called by the IP module when it wants
+ to send a packet on the interface. */
+ err_t (* output)(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+ err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
+
+ /* This field can be set bu the device driver and could point
+ to state information for the device. */
+ void *state;
+};
+
+/* The list of network interfaces. */
+extern struct netif *netif_list;
+extern struct netif *netif_default;
+
+
+/* netif_init() must be called first. */
+void netif_init(void);
+
+struct netif *netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
+ struct ip_addr *gw,
+ void (* init)(struct netif *netif),
+ err_t (* input)(struct pbuf *p, struct netif *netif));
+
+/* Returns a network interface given its name. The name is of the form
+ "et0", where the first two letters are the "name" field in the
+ netif structure, and the digit is in the num field in the same
+ structure. */
+struct netif *netif_find(char *name);
+
+void netif_set_default(struct netif *netif);
+
+void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
+void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
+void netif_set_gw(struct netif *netif, struct ip_addr *gw);
+
+#endif /* __LWIP_NETIF_H__ */
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
new file mode 100644
index 0000000..0c03078
--- /dev/null
+++ b/src/include/lwip/opt.h
@@ -0,0 +1,102 @@
+/*
+ * 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 __LWIP_OPT_H__
+#define __LWIP_OPT_H__
+
+#include "lwipopts.h"
+
+/* Define some handy default values for configuration parameters. */
+
+#ifndef ICMP_TTL
+#define ICMP_TTL 255
+#endif
+
+#ifndef UDP_TTL
+#define UDP_TTL 255
+#endif
+
+#ifndef TCP_TTL
+#define TCP_TTL 255
+#endif
+
+#ifndef TCP_MSS
+#define TCP_MSS 128 /* A *very* conservative default. */
+#endif
+
+#ifndef TCP_WND
+#define TCP_WND 2048
+#endif
+
+#ifndef TCP_MAXRTX
+#define TCP_MAXRTX 12
+#endif
+
+#ifndef TCP_SYNMAXRTX
+#define TCP_SYNMAXRTX 6
+#endif
+
+#ifndef MEM_ALIGNMENT
+#define MEM_ALIGNMENT 1
+#endif
+
+#ifndef PBUF_POOL_SIZE
+#define PBUF_POOL_SIZE 16
+#endif
+
+#ifndef PBUF_POOL_BUFSIZE
+#define PBUF_POOL_BUFSIZE 128
+#endif
+
+#ifndef PBUF_LINK_HLEN
+#define PBUF_LINK_HLEN 0
+#endif
+
+#ifndef LWIP_UDP
+#define LWIP_UDP 1
+#endif
+
+#ifndef LWIP_TCP
+#define LWIP_TCP 1
+#endif
+
+#ifndef LWIP_EVENT_API
+#define LWIP_EVENT_API 0
+#define LWIP_CALLBACK_API 1
+#else
+#define LWIP_EVENT_API 1
+#define LWIP_CALLBACK_API 0
+#endif /* LWIP_CALLBACK_API */
+
+#endif /* __LWIP_OPT_H__ */
+
+
+
diff --git a/src/include/lwip/pbuf.h b/src/include/lwip/pbuf.h
new file mode 100644
index 0000000..cd1ab02
--- /dev/null
+++ b/src/include/lwip/pbuf.h
@@ -0,0 +1,152 @@
+/*
+ * 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 __LWIP_PBUF_H__
+#define __LWIP_PBUF_H__
+
+#include "lwip/debug.h"
+#include "lwip/arch.h"
+
+
+#define PBUF_TRANSPORT_HLEN 20
+#define PBUF_IP_HLEN 20
+
+typedef enum {
+ PBUF_TRANSPORT,
+ PBUF_IP,
+ PBUF_LINK,
+ PBUF_RAW
+} pbuf_layer;
+
+typedef enum {
+ PBUF_RAM,
+ PBUF_ROM,
+ PBUF_POOL
+} pbuf_flag;
+
+/* Definitions for the pbuf flag field (these are not the flags that
+ are passed to pbuf_alloc()). */
+#define PBUF_FLAG_RAM 0x00 /* Flags that pbuf data is stored in RAM. */
+#define PBUF_FLAG_ROM 0x01 /* Flags that pbuf data is stored in ROM. */
+#define PBUF_FLAG_POOL 0x02 /* Flags that the pbuf comes from the
+ pbuf pool. */
+
+struct pbuf {
+ struct pbuf *next;
+
+ /* Pointer to the actual data in the buffer. */
+ void *payload;
+
+ /* Total length of buffer + additionally chained buffers. */
+ u16_t tot_len;
+
+ /* Length of this buffer. */
+ u16_t len;
+
+ /* Flags and reference count. */
+ u16_t flags, ref;
+
+};
+
+/* pbuf_init():
+
+ Initializes the pbuf module. The num parameter determines how many
+ pbufs that should be allocated to the pbuf pool, and the size
+ parameter specifies the size of the data allocated to those. */
+void pbuf_init(void);
+
+/* pbuf_alloc():
+
+ Allocates a pbuf at protocol layer l. The actual memory allocated
+ for the pbuf is determined by the layer at which the pbuf is
+ allocated and the requested size (from the size parameter). The
+ flag parameter decides how and where the pbuf should be allocated
+ as follows:
+
+ * PBUF_RAM: buffer memory for pbuf is allocated as one large
+ chunk. This includesprotocol headers as well.
+
+ * RBUF_ROM: no buffer memory is allocated for the pbuf, even for
+ protocol headers. Additional headers must be
+ prepended by allocating another pbuf and chain in to
+ the front of the ROM pbuf.
+
+ * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
+ the pbuf pool that is allocated during pbuf_init(). */
+struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
+
+/* pbuf_realloc():
+
+ Shrinks the pbuf to the size given by the size parameter.
+ */
+void pbuf_realloc(struct pbuf *p, u16_t size);
+
+/* pbuf_header():
+
+ Tries to move the p->payload pointer header_size number of bytes
+ upward within the pbuf. The return value is non-zero if it
+ fails. If so, an additional pbuf should be allocated for the header
+ and it should be chained to the front. */
+u8_t pbuf_header(struct pbuf *p, s16_t header_size);
+
+/* pbuf_ref():
+
+ Increments the reference count of the pbuf p.
+ */
+void pbuf_ref(struct pbuf *p);
+
+/* pbuf_free():
+
+ Decrements the reference count and deallocates the pbuf if the
+ reference count is zero. If the pbuf is a chain all pbufs in the
+ chain are deallocated. */
+u8_t pbuf_free(struct pbuf *p);
+
+/* pbuf_clen():
+
+ Returns the length of the pbuf chain. */
+u8_t pbuf_clen(struct pbuf *p);
+
+/* pbuf_chain():
+
+ Chains pbuf t on the end of pbuf h. Pbuf h will have it's tot_len
+ field adjusted accordingly. Pbuf t should no be used any more after
+ a call to this function, since pbuf t is now a part of pbuf h. */
+void pbuf_chain(struct pbuf *h, struct pbuf *t);
+
+/* pbuf_dechain():
+
+ Picks off the first pbuf from the pbuf chain p. Returns the tail of
+ the pbuf chain or NULL if the pbuf p was not chained. */
+struct pbuf *pbuf_dechain(struct pbuf *p);
+
+#endif /* __LWIP_PBUF_H__ */
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
new file mode 100644
index 0000000..f6baa91
--- /dev/null
+++ b/src/include/lwip/sockets.h
@@ -0,0 +1,99 @@
+/*
+ * 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 __LWIP_SOCKETS_H__
+#define __LWIP_SOCKETS_H__
+
+struct in_addr {
+ u32_t s_addr;
+};
+
+
+struct sockaddr_in {
+ u8_t sin_len;
+ u8_t sin_family;
+ u16_t sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+struct sockaddr {
+ u8_t sa_len;
+ u8_t sa_family;
+ char sa_data[14];
+};
+
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+
+#define AF_INET 2
+#define PF_INET AF_INET
+
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+
+#define INADDR_ANY 0
+#define INADDR_BROADCAST 0xffffffff
+
+int lwip_accept(int s, struct sockaddr *addr, int *addrlen);
+int lwip_bind(int s, struct sockaddr *name, int namelen);
+int lwip_close(int s);
+int lwip_connect(int s, struct sockaddr *name, int namelen);
+int lwip_listen(int s, int backlog);
+int lwip_recv(int s, void *mem, int len, unsigned int flags);
+int lwip_read(int s, void *mem, int len);
+int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen);
+int lwip_send(int s, void *dataptr, int size, unsigned int flags);
+int lwip_sendto(int s, void *dataptr, int size, unsigned int flags,
+ struct sockaddr *to, int tolen);
+int lwip_socket(int domain, int type, int protocol);
+int lwip_write(int s, void *dataptr, int size);
+
+#ifdef LWIP_COMPAT_SOCKETS
+#define accept(a,b,c) lwip_accept(a,b,c)
+#define bind(a,b,c) lwip_bind(a,b,c)
+#define close(s) lwip_close(s)
+#define connect(a,b,c) lwip_connect(a,b,c)
+#define listen(a,b) lwip_listen(a,b)
+#define recv(a,b,c,d) lwip_recv(a,b,c,d)
+#define read(a,b,c) lwip_read(a,b,c)
+#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
+#define send(a,b,c,d) lwip_send(a,b,c,d)
+#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f)
+#define socket(a,b,c) lwip_socket(a,b,c)
+#define write(a,b,c) lwip_write(a,b,c)
+#endif /* LWIP_NO_COMPAT_SOCKETS */
+
+#endif /* __LWIP_SOCKETS_H__ */
+
diff --git a/src/include/lwip/stats.h b/src/include/lwip/stats.h
new file mode 100644
index 0000000..024b9ae
--- /dev/null
+++ b/src/include/lwip/stats.h
@@ -0,0 +1,109 @@
+/*
+ * 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 __LWIP_STATS_H__
+#define __LWIP_STATS_H__
+
+#include "lwip/opt.h"
+#include "arch/cc.h"
+
+#include "lwip/memp.h"
+
+#ifdef STATS
+
+struct stats_proto {
+ u16_t xmit; /* Transmitted packets. */
+ u16_t rexmit; /* Retransmitted packets. */
+ u16_t recv; /* Received packets. */
+ u16_t fw; /* Forwarded packets. */
+ u16_t drop; /* Dropped packets. */
+ u16_t chkerr; /* Checksum error. */
+ u16_t lenerr; /* Invalid length error. */
+ u16_t memerr; /* Out of memory error. */
+ u16_t rterr; /* Routing error. */
+ u16_t proterr; /* Protocol error. */
+ u16_t opterr; /* Error in options. */
+ u16_t err; /* Misc error. */
+ u16_t cachehit;
+};
+
+struct stats_mem {
+ u16_t avail;
+ u16_t used;
+ u16_t max;
+ u16_t err;
+ u16_t reclaimed;
+};
+
+struct stats_pbuf {
+ u16_t avail;
+ u16_t used;
+ u16_t max;
+ u16_t err;
+ u16_t reclaimed;
+
+ u16_t alloc_locked;
+ u16_t refresh_locked;
+};
+
+struct stats_syselem {
+ u16_t used;
+ u16_t max;
+ u16_t err;
+};
+
+struct stats_sys {
+ struct stats_syselem sem;
+ struct stats_syselem mbox;
+};
+
+struct stats_ {
+ struct stats_proto link;
+ struct stats_proto ip;
+ struct stats_proto icmp;
+ struct stats_proto udp;
+ struct stats_proto tcp;
+ struct stats_pbuf pbuf;
+ struct stats_mem mem;
+ struct stats_mem memp[MEMP_MAX];
+ struct stats_sys sys;
+};
+
+extern struct stats_ stats;
+
+#endif /* STATS */
+
+void stats_init(void);
+#endif /* __LWIP_STATS_H__ */
+
+
+
+
diff --git a/src/include/lwip/sys.h b/src/include/lwip/sys.h
new file mode 100644
index 0000000..2246d0c
--- /dev/null
+++ b/src/include/lwip/sys.h
@@ -0,0 +1,116 @@
+/*
+ * 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 __LWIP_SYS_H__
+#define __LWIP_SYS_H__
+
+#include "arch/cc.h"
+
+#include "lwip/opt.h"
+
+#if NO_SYS
+
+/* For a totally minimal and standalone system, we provide null
+ definitions of the sys_ functions. */
+typedef u8_t sys_sem_t;
+typedef u8_t sys_mbox_t;
+struct sys_timeout {u8_t dummy;};
+
+#define sys_init()
+#define sys_timeout(m,h,a)
+#define sys_sem_new(c) c
+#define sys_sem_signal(s)
+#define sys_sem_wait(s)
+#define sys_sem_free(s)
+#define sys_mbox_new() 0
+#define sys_mbox_fetch(m,d)
+#define sys_mbox_post(m,d)
+#define sys_mbox_free(m)
+
+#define sys_thread_new(t,a)
+
+#else /* NO_SYS */
+
+#include "arch/sys_arch.h"
+
+typedef void (* sys_timeout_handler)(void *arg);
+
+struct sys_timeout {
+ struct sys_timeout *next;
+ u16_t time;
+ sys_timeout_handler h;
+ void *arg;
+};
+
+struct sys_timeouts {
+ struct sys_timeout *next;
+};
+
+/* sys_init() must be called before anthing else. */
+void sys_init(void);
+
+/*
+ * sys_timeout():
+ *
+ * Schedule a timeout a specified amount of milliseconds in the
+ * future. When the timeout occurs, the specified timeout handler will
+ * be called. The handler will be passed the "arg" argument when
+ * called.
+ *
+ */
+void sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg);
+struct sys_timeouts *sys_arch_timeouts(void);
+
+/* Semaphore functions. */
+sys_sem_t sys_sem_new(u8_t count);
+void sys_sem_signal(sys_sem_t sem);
+u16_t sys_arch_sem_wait(sys_sem_t sem, u16_t timeout);
+void sys_sem_free(sys_sem_t sem);
+void sys_sem_wait(sys_sem_t sem);
+
+/* Mailbox functions. */
+sys_mbox_t sys_mbox_new(void);
+void sys_mbox_post(sys_mbox_t mbox, void *msg);
+u16_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u16_t timeout);
+void sys_mbox_free(sys_mbox_t mbox);
+void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
+
+/* Thread functions. */
+void sys_thread_new(void (* thread)(void *arg), void *arg);
+
+/* The following functions are used only in Unix code, and
+ can be omitted when porting the stack. */
+/* Returns the current time in microseconds. */
+unsigned long sys_now(void);
+
+#endif /* NO_SYS */
+
+#endif /* __LWIP_SYS_H__ */
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
new file mode 100644
index 0000000..b8e5cad
--- /dev/null
+++ b/src/include/lwip/tcp.h
@@ -0,0 +1,448 @@
+/*
+ * 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 __LWIP_TCP_H__
+#define __LWIP_TCP_H__
+
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+
+#include "lwip/pbuf.h"
+#include "lwip/opt.h"
+#include "lwip/ip.h"
+#include "lwip/icmp.h"
+
+#include "lwip/sys.h"
+
+#include "lwip/err.h"
+
+#include "lwip/event.h"
+
+struct tcp_pcb;
+
+/* Functions for interfacing with TCP: */
+
+/* Lower layer interface to TCP: */
+void tcp_init (void); /* Must be called first to
+ initialize TCP. */
+void tcp_tmr (void); /* Must be called every
+ TCP_TMR_INTERVAL
+ ms. (Typically 100 ms). */
+/* Application program's interface: */
+struct tcp_pcb * tcp_new (void);
+struct tcp_pcb * tcp_alloc (u8_t prio);
+
+void tcp_arg (struct tcp_pcb *pcb, void *arg);
+void tcp_accept (struct tcp_pcb *pcb,
+ err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
+ err_t err));
+void tcp_recv (struct tcp_pcb *pcb,
+ err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
+ struct pbuf *p, err_t err));
+void tcp_sent (struct tcp_pcb *pcb,
+ err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
+ u16_t len));
+void tcp_poll (struct tcp_pcb *pcb,
+ err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
+ u8_t interval);
+void tcp_err (struct tcp_pcb *pcb,
+ void (* err)(void *arg, err_t err));
+
+#define tcp_mss(pcb) ((pcb)->mss)
+#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
+
+void tcp_recved (struct tcp_pcb *pcb, u16_t len);
+err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
+ u16_t port);
+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));
+struct tcp_pcb * tcp_listen (struct tcp_pcb *pcb);
+void tcp_abort (struct tcp_pcb *pcb);
+err_t tcp_close (struct tcp_pcb *pcb);
+err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
+ u8_t copy);
+
+void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
+
+#define TCP_PRIO_MIN 1
+#define TCP_PRIO_NORMAL 64
+#define TCP_PRIO_MAX 127
+
+/* It is also possible to call these two functions at the right
+ intervals (instead of calling tcp_tmr()). */
+void tcp_slowtmr (void);
+void tcp_fasttmr (void);
+
+
+/* Only used by IP to pass a TCP segment to TCP: */
+void tcp_input (struct pbuf *p, struct netif *inp);
+/* Used within the TCP code only: */
+err_t tcp_output (struct tcp_pcb *pcb);
+void tcp_rexmit (struct tcp_pcb *pcb);
+
+
+
+#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
+#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
+#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
+#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
+
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_PSH 0x08
+#define TCP_ACK 0x10
+#define TCP_URG 0x20
+
+#define TCP_FLAGS 0x3f
+
+/* Length of the TCP header, excluding options. */
+#define TCP_HLEN 20
+
+#define TCP_TMR_INTERVAL 100 /* The TCP timer interval in
+ milliseconds. */
+
+#define TCP_FAST_INTERVAL 200 /* the fine grained timeout in
+ milliseconds */
+#define TCP_SLOW_INTERVAL 500 /* the coarse grained timeout in
+ milliseconds */
+#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
+#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
+
+#define TCP_OOSEQ_TIMEOUT 6 /* x RTO */
+
+#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
+
+PACK_STRUCT_BEGIN
+struct tcp_hdr {
+ PACK_STRUCT_FIELD(u16_t src);
+ PACK_STRUCT_FIELD(u16_t dest);
+ PACK_STRUCT_FIELD(u32_t seqno);
+ PACK_STRUCT_FIELD(u32_t ackno);
+ PACK_STRUCT_FIELD(u16_t _offset_flags);
+ PACK_STRUCT_FIELD(u16_t wnd);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u16_t urgp);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define TCPH_OFFSET(hdr) (NTOHS((hdr)->_offset_flags) >> 8)
+#define TCPH_FLAGS(hdr) (NTOHS((hdr)->_offset_flags) & 0xff)
+
+#define TCPH_OFFSET_SET(hdr, offset) (hdr)->_offset_flags = HTONS(((offset) << 8) | TCPH_FLAGS(hdr))
+#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = HTONS((TCPH_OFFSET(hdr) << 8) | (flags))
+
+#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
+ TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
+
+enum tcp_state {
+ CLOSED = 0,
+ LISTEN = 1,
+ SYN_SENT = 2,
+ SYN_RCVD = 3,
+ ESTABLISHED = 4,
+ FIN_WAIT_1 = 5,
+ FIN_WAIT_2 = 6,
+ CLOSE_WAIT = 7,
+ CLOSING = 8,
+ LAST_ACK = 9,
+ TIME_WAIT = 10
+};
+
+
+/* the TCP protocol control block */
+struct tcp_pcb {
+ struct tcp_pcb *next; /* for the linked list */
+ u8_t prio;
+ void *callback_arg;
+
+ struct ip_addr local_ip;
+ u16_t local_port;
+
+ struct ip_addr remote_ip;
+ u16_t remote_port;
+
+ /* receiver varables */
+ u32_t rcv_nxt; /* next seqno expected */
+ u16_t rcv_wnd; /* receiver window */
+
+ enum tcp_state state; /* TCP state */
+
+ /* Timers */
+ u16_t tmr;
+ u8_t polltmr, pollinterval;
+
+ /* Retransmission timer. */
+ u8_t rtime;
+
+ u16_t mss; /* maximum segment size */
+
+ u8_t flags;
+#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
+#define TF_ACK_NOW 0x02U /* Immediate ACK. */
+#define TF_INFR 0x04U /* In fast recovery. */
+#define TF_RESET 0x08U /* Connection was reset. */
+#define TF_CLOSED 0x10U /* Connection was sucessfully closed. */
+#define TF_GOT_FIN 0x20U /* Connection was closed by the remote end. */
+
+ /* RTT estimation variables. */
+ u16_t rttest; /* RTT estimate in 500ms ticks */
+ u32_t rtseq; /* sequence number being timed */
+ s16_t sa, sv;
+
+ u16_t rto; /* retransmission time-out */
+ u8_t nrtx; /* number of retransmissions */
+
+ /* fast retransmit/recovery */
+ u32_t lastack; /* Highest acknowledged seqno. */
+ u8_t dupacks;
+
+ /* congestion avoidance/control variables */
+ u16_t cwnd;
+ u16_t ssthresh;
+
+ /* sender variables */
+ u32_t snd_nxt, /* next seqno to be sent */
+ snd_max, /* Highest seqno sent. */
+ snd_wnd, /* sender window */
+ snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last
+ window update. */
+ snd_lbb; /* Sequence number of next byte to be buffered. */
+
+ u16_t acked;
+
+ u16_t snd_buf; /* Avaliable buffer space for sending (in bytes). */
+ u8_t snd_queuelen; /* Avaliable buffer space for sending (in tcp_segs). */
+
+
+ /* These are ordered by sequence number: */
+ struct tcp_seg *unsent; /* Unsent (queued) segments. */
+ struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
+#if TCP_QUEUE_OOSEQ
+ struct tcp_seg *ooseq; /* Received out of sequence segments. */
+#endif /* TCP_QUEUE_OOSEQ */
+
+#if LWIP_CALLBACK_API
+ /* Function to be called when more send buffer space is avaliable. */
+ err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
+
+ /* Function to be called when (in-sequence) data has arrived. */
+ err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
+
+ /* Function to be called when a connection has been set up. */
+ err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
+
+ /* Function to call when a listener has been connected. */
+ err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
+
+ /* Function which is called periodically. */
+ err_t (* poll)(void *arg, struct tcp_pcb *pcb);
+
+ /* Function to be called whenever a fatal error occurs. */
+ void (* errf)(void *arg, err_t err);
+#endif /* LWIP_CALLBACK_API */
+};
+
+struct tcp_pcb_listen {
+ struct tcp_pcb_listen *next; /* for the linked list */
+ u8_t prio;
+ void *callback_arg;
+
+ struct ip_addr local_ip;
+ u16_t local_port;
+
+#if LWIP_CALLBACK_API
+ /* Function to call when a listener has been connected. */
+ err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
+#endif /* LWIP_CALLBACK_API */
+};
+
+#if LWIP_EVENT_API
+#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_ACCEPT, NULL, 0, err)
+#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_SENT, NULL, space, ERR_OK)
+#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_RECV, (p), 0, (err))
+#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_CONNECTED, NULL, 0, (err))
+#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_POLL, NULL, 0, ERR_OK)
+#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
+ LWIP_EVENT_ERR, NULL, 0, (err))
+#else /* LWIP_EVENT_API */
+#define TCP_EVENT_ACCEPT(pcb,err,ret) \
+ if((pcb)->accept != NULL) \
+ (ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
+#define TCP_EVENT_SENT(pcb,space,ret) \
+ if((pcb)->sent != NULL) \
+ (ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
+#define TCP_EVENT_RECV(pcb,p,err,ret) \
+ if((pcb)->recv != NULL) \
+ (ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)))
+#define TCP_EVENT_CONNECTED(pcb,err,ret) \
+ if((pcb)->connected != NULL) \
+ (ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
+#define TCP_EVENT_POLL(pcb,ret) \
+ if((pcb)->poll != NULL) \
+ (ret = (pcb)->poll((pcb)->callback_arg,(pcb)))
+#define TCP_EVENT_ERR(errf,arg,err) \
+ if((errf) != NULL) \
+ (errf)((arg),(err))
+#endif /* LWIP_EVENT_API */
+
+/* This structure is used to repressent TCP segments when queued. */
+struct tcp_seg {
+ struct tcp_seg *next; /* used when putting segements on a queue */
+ struct pbuf *p; /* buffer containing data + TCP header */
+ void *dataptr; /* pointer to the TCP data in the pbuf */
+ u16_t len; /* the TCP length of this segment */
+ struct tcp_hdr *tcphdr; /* the TCP header */
+};
+
+/* Internal functions and global variables: */
+struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
+void tcp_pcb_purge(struct tcp_pcb *pcb);
+void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
+
+u8_t tcp_segs_free(struct tcp_seg *seg);
+u8_t tcp_seg_free(struct tcp_seg *seg);
+struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
+
+#define tcp_ack(pcb) if((pcb)->flags & TF_ACK_DELAY) { \
+ (pcb)->flags &= ~TF_ACK_DELAY; \
+ (pcb)->flags |= TF_ACK_NOW; \
+ tcp_output(pcb); \
+ } else { \
+ (pcb)->flags |= TF_ACK_DELAY; \
+ }
+
+#define tcp_ack_now(pcb) (pcb)->flags |= TF_ACK_NOW; \
+ tcp_output(pcb)
+
+err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
+err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
+ u8_t flags, u8_t copy,
+ u8_t *optdata, u8_t optlen);
+
+void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
+
+void tcp_rst(u32_t seqno, u32_t ackno,
+ struct ip_addr *local_ip, struct ip_addr *remote_ip,
+ u16_t local_port, u16_t remote_port);
+
+u32_t tcp_next_iss(void);
+
+extern struct tcp_pcb *tcp_input_pcb;
+extern u32_t tcp_ticks;
+
+#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
+void tcp_debug_print(struct tcp_hdr *tcphdr);
+void tcp_debug_print_flags(u8_t flags);
+void tcp_debug_print_state(enum tcp_state s);
+void tcp_debug_print_pcbs(void);
+int tcp_pcbs_sane(void);
+#else
+#define tcp_pcbs_sane() 1
+#endif /* TCP_DEBUG */
+
+
+/* The TCP PCB lists. */
+extern struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
+extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
+ state in which they accept or send
+ data. */
+extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
+
+extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
+
+/* Axoims about the above lists:
+ 1) Every TCP PCB that is not CLOSED is in one of the lists.
+ 2) A PCB is only in one of the lists.
+ 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
+ 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
+*/
+
+/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
+ with a PCB list or removes a PCB from a list, respectively. */
+#if 0
+#define TCP_REG(pcbs, npcb) do {\
+ DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
+ for(tcp_tmp_pcb = *pcbs; \
+ tcp_tmp_pcb != NULL; \
+ tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
+ } \
+ ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
+ npcb->next = *pcbs; \
+ ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
+ *(pcbs) = npcb; \
+ ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+ } while(0)
+#define TCP_RMV(pcbs, npcb) do { \
+ ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
+ DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
+ if(*pcbs == npcb) { \
+ *pcbs = (*pcbs)->next; \
+ } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
+ tcp_tmp_pcb->next = npcb->next; \
+ break; \
+ } \
+ } \
+ npcb->next = NULL; \
+ ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+ DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
+ } while(0)
+
+#else /* LWIP_DEBUG */
+#define TCP_REG(pcbs, npcb) do { \
+ npcb->next = *pcbs; \
+ *(pcbs) = npcb; \
+ } while(0)
+#define TCP_RMV(pcbs, npcb) do { \
+ if(*(pcbs) == npcb) { \
+ (*(pcbs)) = (*pcbs)->next; \
+ } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
+ tcp_tmp_pcb->next = npcb->next; \
+ break; \
+ } \
+ } \
+ npcb->next = NULL; \
+ } while(0)
+#endif /* LWIP_DEBUG */
+#endif /* __LWIP_TCP_H__ */
+
+
+
diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h
new file mode 100644
index 0000000..fbd9b87
--- /dev/null
+++ b/src/include/lwip/tcpip.h
@@ -0,0 +1,60 @@
+/*
+ * 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 __LWIP_TCPIP_H__
+#define __LWIP_TCPIP_H__
+
+#include "lwip/api_msg.h"
+#include "lwip/pbuf.h"
+
+void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
+void tcpip_apimsg(struct api_msg *apimsg);
+err_t tcpip_input(struct pbuf *p, struct netif *inp);
+
+enum tcpip_msg_type {
+ TCPIP_MSG_API,
+ TCPIP_MSG_INPUT
+};
+
+struct tcpip_msg {
+ enum tcpip_msg_type type;
+ sys_sem_t *sem;
+ union {
+ struct api_msg *apimsg;
+ struct {
+ struct pbuf *p;
+ struct netif *netif;
+ } inp;
+ } msg;
+};
+
+
+#endif /* __LWIP_TCPIP_H__ */
diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h
new file mode 100644
index 0000000..2528376
--- /dev/null
+++ b/src/include/lwip/udp.h
@@ -0,0 +1,97 @@
+/*
+ * 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 __LWIP_UDP_H__
+#define __LWIP_UDP_H__
+
+#include "lwip/arch.h"
+
+#include "lwip/pbuf.h"
+#include "lwip/inet.h"
+#include "lwip/ip.h"
+
+#include "lwip/err.h"
+
+#define UDP_HLEN 8
+
+struct udp_hdr {
+ PACK_STRUCT_FIELD(u16_t src);
+ PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */
+ PACK_STRUCT_FIELD(u16_t len);
+ PACK_STRUCT_FIELD(u16_t chksum);
+} PACK_STRUCT_STRUCT;
+
+#define UDP_FLAGS_NOCHKSUM 0x01
+#define UDP_FLAGS_UDPLITE 0x02
+
+struct udp_pcb {
+ struct udp_pcb *next;
+
+ struct ip_addr local_ip, remote_ip;
+ u16_t local_port, remote_port;
+
+ u8_t flags;
+ u16_t chksum_len;
+
+ void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
+ struct ip_addr *addr, u16_t port);
+ void *recv_arg;
+};
+
+/* The following functions is the application layer interface to the
+ UDP code. */
+struct udp_pcb * udp_new (void);
+void udp_remove (struct udp_pcb *pcb);
+err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr,
+ u16_t port);
+err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr,
+ u16_t port);
+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);
+err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
+
+#define udp_flags(pcb) ((pcb)->flags)
+#define udp_setflags(pcb, f) ((pcb)->flags = (f))
+
+
+/* The following functions is the lower layer interface to UDP. */
+u8_t udp_lookup (struct ip_hdr *iphdr, struct netif *inp);
+void udp_input (struct pbuf *p, struct netif *inp);
+void udp_init (void);
+
+
+#endif /* __LWIP_UDP_H__ */
+
+
diff --git a/src/include/netif/etharp.h b/src/include/netif/etharp.h
new file mode 100644
index 0000000..5d56d7b
--- /dev/null
+++ b/src/include/netif/etharp.h
@@ -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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Swedish Institute
+ * of Computer Science and its contributors.
+ * 4. 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>
+ *
+ *
+ */
+
+#ifndef __NETIF_ETHARP_H__
+#define __NETIF_ETHARP_H__
+
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+#include "lwip/netif.h"
+
+PACK_STRUCT_BEGIN
+struct eth_addr {
+ PACK_STRUCT_FIELD(u8_t addr[6]);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+struct eth_hdr {
+ PACK_STRUCT_FIELD(struct eth_addr dest);
+ PACK_STRUCT_FIELD(struct eth_addr src);
+ PACK_STRUCT_FIELD(u16_t type);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define ARP_TMR_INTERVAL 10000
+
+#define ETHTYPE_ARP 0x0806
+#define ETHTYPE_IP 0x0800
+
+/* Initializes ARP. */
+void etharp_init(void);
+
+/* The etharp_tmr() function should be called every ETHARP_TMR_INTERVAL
+ microseconds (10 seconds). This function is responsible for
+ expiring old entries in the ARP table. */
+void etharp_tmr(void);
+
+/* Should be called for all incoming packets of IP kind. The function
+ does not alter the packet in any way, it just updates the ARP
+ table. After this function has been called, the normal TCP/IP stack
+ input function should be called.
+
+ The function may return a pbuf containing a packet that had
+ previously been queued for transmission. The device driver must
+ transmit this packet onto the network, and call pbuf_free() for the
+ pbuf.
+*/
+struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
+
+/* Should be called for incoming ARP packets. The pbuf in the argument
+ is freed by this function. If the function returns a pbuf (i.e.,
+ returns non-NULL), that pbuf constitutes an ARP reply and should be
+ sent out on the Ethernet.
+
+ The driver must call pbuf_free() for the returned pbuf when the
+ packet has been sent.
+*/
+struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
+ struct pbuf *p);
+
+
+/* The etharp_output() function should be called for all outgoing
+ packets. The pbuf returned by the function should be sent out on
+ the Ethernet.
+
+ The function prepares the packet for transmission over the Ethernet
+ by adding an Ethernet header. If there is no IP -> MAC address
+ mapping, the function will queue the outgoing packet and return an
+ ARP request.
+*/
+struct pbuf *etharp_output(struct netif *netif, struct ip_addr *ipaddr,
+ struct pbuf *q);
+
+
+#endif /* __NETIF_ARP_H__ */
diff --git a/src/include/netif/ethernetif.h b/src/include/netif/ethernetif.h
new file mode 100644
index 0000000..d0ae690
--- /dev/null
+++ b/src/include/netif/ethernetif.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __NETIF_ETHERNETIF_H__
+#define __NETIF_ETHERNETIF_H__
+
+#include "lwip/netif.h"
+
+void ethernetif_init(struct netif *netif);
+
+#endif /* __NETIF_ETHERNETIF_H__ */
diff --git a/src/include/netif/loopif.h b/src/include/netif/loopif.h
new file mode 100644
index 0000000..ffc76e9
--- /dev/null
+++ b/src/include/netif/loopif.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __NETIF_LOOPIF_H__
+#define __NETIF_LOOPIF_H__
+
+#include "lwip/netif.h"
+
+void loopif_init(struct netif *netif);
+
+#endif /* __NETIF_LOOPIF_H__ */
diff --git a/src/include/netif/tcpdump.h b/src/include/netif/tcpdump.h
new file mode 100644
index 0000000..d74b1fe
--- /dev/null
+++ b/src/include/netif/tcpdump.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __NETIF_TCPDUMP_H__
+#define __NETIF_TCPDUMP_H__
+
+#include "lwip/pbuf.h"
+
+void tcpdump_init(void);
+void tcpdump(struct pbuf *p);
+
+#endif /* __NETIF_TCPDUMP_H__ */
diff --git a/src/netif/etharp.c b/src/netif/etharp.c
new file mode 100644
index 0000000..b311589
--- /dev/null
+++ b/src/netif/etharp.c
@@ -0,0 +1,474 @@
+/*
+ * 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/opt.h"
+#include "lwip/debug.h"
+#include "lwip/inet.h"
+#include "netif/etharp.h"
+#include "lwip/ip.h"
+#include "lwip/stats.h"
+
+#if LWIP_DHCP
+# include "lwip/dhcp.h"
+#endif
+
+
+#define ARP_MAXAGE 120 /* 120 * 10 seconds = 20 minutes. */
+#define ARP_MAXPENDING 2 /* 2 * 10 seconds = 20 seconds. */
+
+#define HWTYPE_ETHERNET 1
+
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+/* MUST be compiled with "pack structs" or equivalent! */
+PACK_STRUCT_BEGIN
+struct etharp_hdr {
+ PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
+ PACK_STRUCT_FIELD(u16_t hwtype);
+ PACK_STRUCT_FIELD(u16_t proto);
+ PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
+ PACK_STRUCT_FIELD(u16_t opcode);
+ PACK_STRUCT_FIELD(struct eth_addr shwaddr);
+ PACK_STRUCT_FIELD(struct ip_addr sipaddr);
+ PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
+ PACK_STRUCT_FIELD(struct ip_addr dipaddr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define ARPH_HWLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) >> 8)
+#define ARPH_PROTOLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) & 0xff)
+
+
+#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS(ARPH_PROTOLEN(hdr) | ((len) << 8))
+#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS((len) | (ARPH_HWLEN(hdr) << 8))
+
+PACK_STRUCT_BEGIN
+struct ethip_hdr {
+ PACK_STRUCT_FIELD(struct eth_hdr eth);
+ PACK_STRUCT_FIELD(struct ip_hdr ip);
+};
+PACK_STRUCT_END
+
+enum etharp_state {
+ ETHARP_STATE_EMPTY,
+ ETHARP_STATE_PENDING,
+ ETHARP_STATE_STABLE
+};
+
+struct etharp_entry {
+ struct ip_addr ipaddr;
+ struct eth_addr ethaddr;
+ enum etharp_state state;
+ struct pbuf *p;
+ void *payload;
+ u16_t len, tot_len;
+ u8_t ctime;
+};
+
+static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+static struct etharp_entry arp_table[ARP_TABLE_SIZE];
+static u8_t ctime;
+
+/*-----------------------------------------------------------------------------------*/
+void
+etharp_init(void)
+{
+ u8_t i;
+
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ arp_table[i].state = ETHARP_STATE_EMPTY;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+etharp_tmr(void)
+{
+ u8_t i;
+
+ ++ctime;
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ if(arp_table[i].state == ETHARP_STATE_STABLE &&
+ ctime - arp_table[i].ctime >= ARP_MAXAGE) {
+ DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %d.\n", i));
+ arp_table[i].state = ETHARP_STATE_EMPTY;
+ } else if(arp_table[i].state == ETHARP_STATE_PENDING &&
+ ctime - arp_table[i].ctime >= ARP_MAXPENDING) {
+ DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %d - dequeueing %p.\n", i, arp_table[i].p));
+ arp_table[i].state = ETHARP_STATE_EMPTY;
+ pbuf_free(arp_table[i].p);
+ }
+ }
+}
+/*----------------------------------------------------------------------------------*/
+static u8_t
+find_arp_entry(void)
+{
+ u8_t i, j, maxtime;
+
+ /* Try to find an unused entry in the ARP table. */
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ if(arp_table[i].state == ETHARP_STATE_EMPTY) {
+ break;
+ }
+ }
+
+ /* If no unused entry is found, we try to find the oldest entry and
+ throw it away. */
+ if(i == ARP_TABLE_SIZE) {
+ maxtime = 0;
+ j = 0;
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ if(arp_table[i].state == ETHARP_STATE_STABLE &&
+ ctime - arp_table[i].ctime > maxtime) {
+ maxtime = ctime - arp_table[i].ctime;
+ j = i;
+ }
+ }
+ i = j;
+ }
+ return i;
+}
+/*-----------------------------------------------------------------------------------*/
+static struct pbuf *
+update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
+{
+ u8_t i, k;
+ struct pbuf *p;
+ struct eth_hdr *ethhdr;
+
+ /* Walk through the ARP mapping table and try to find an entry to
+ update. If none is found, the IP -> MAC address mapping is
+ inserted in the ARP table. */
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ /* Check if the source IP address of the incoming packet matches
+ the IP address in this ARP table entry. */
+ if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
+
+ /* First, check those entries that are already in use. */
+ if(arp_table[i].state == ETHARP_STATE_STABLE) {
+ /* An old entry found, update this and return. */
+ for(k = 0; k < 6; ++k) {
+ arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
+ }
+ arp_table[i].ctime = ctime;
+ return NULL;
+ }
+ if(arp_table[i].state == ETHARP_STATE_PENDING) {
+ /* A pending entry was found, so we fill this in and return
+ the queued packet (if any). */
+ for(k = 0; k < 6; ++k) {
+ arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
+ }
+ arp_table[i].ctime = ctime;
+ arp_table[i].state = ETHARP_STATE_STABLE;
+ p = arp_table[i].p;
+ if(p != NULL) {
+ p->payload = arp_table[i].payload;
+ p->len = arp_table[i].len;
+ p->tot_len = arp_table[i].tot_len;
+ arp_table[i].p = NULL;
+
+ ethhdr = p->payload;
+
+ for(k = 0; k < 6; ++k) {
+ ethhdr->dest.addr[k] = ethaddr->addr[k];
+ }
+
+ ethhdr->type = htons(ETHTYPE_IP);
+ }
+ return p;
+ }
+ }
+ }
+ /* We get here if no ARP entry was found. If so, we create one. */
+ i = find_arp_entry();
+ if(i == ARP_TABLE_SIZE) {
+ return NULL;
+ }
+
+ ip_addr_set(&arp_table[i].ipaddr, ipaddr);
+ for(k = 0; k < 6; ++k) {
+ arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
+ }
+ arp_table[i].ctime = ctime;
+ arp_table[i].state = ETHARP_STATE_STABLE;
+ arp_table[i].p = NULL;
+
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+struct pbuf *
+etharp_ip_input(struct netif *netif, struct pbuf *p)
+{
+ struct ethip_hdr *hdr;
+
+ hdr = p->payload;
+
+ /* Only insert/update an entry if the source IP address of the
+ incoming IP packet comes from a host on the local network. */
+ if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
+ return NULL;
+ }
+ DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
+ return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
+}
+/*-----------------------------------------------------------------------------------*/
+struct pbuf *
+etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
+{
+ struct etharp_hdr *hdr;
+ u8_t i;
+
+ if(p->tot_len < sizeof(struct etharp_hdr)) {
+ DEBUGF(ETHARP_DEBUG, ("etharp_etharp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
+ pbuf_free(p);
+ return NULL;
+ }
+
+ hdr = p->payload;
+
+ switch(htons(hdr->opcode)) {
+ case ARP_REQUEST:
+ /* ARP request. If it asked for our address, we send out a
+ reply. */
+ DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request\n"));
+ if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
+ hdr->opcode = htons(ARP_REPLY);
+
+ ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
+ ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
+
+ for(i = 0; i < 6; ++i) {
+ hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
+ hdr->shwaddr.addr[i] = ethaddr->addr[i];
+ hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
+ hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
+ }
+
+ hdr->hwtype = htons(HWTYPE_ETHERNET);
+ ARPH_HWLEN_SET(hdr, 6);
+
+ hdr->proto = htons(ETHTYPE_IP);
+ ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
+
+ hdr->ethhdr.type = htons(ETHTYPE_ARP);
+ return p;
+ }
+ break;
+ case ARP_REPLY:
+ /* ARP reply. We insert or update the ARP table. */
+ DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n"));
+ if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
+#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
+ dhcp_arp_reply(&hdr->sipaddr);
+#endif
+ /* update_arp_entry() will return a pbuf that has previously been
+ queued waiting for an ARP reply. */
+ pbuf_free(p);
+ p = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
+
+ return p;
+ }
+ break;
+ default:
+ DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode)));
+ break;
+ }
+
+ pbuf_free(p);
+ return NULL;
+}
+/*-----------------------------------------------------------------------------------*/
+struct pbuf *
+etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
+{
+ struct eth_addr *dest, *srcaddr, mcastaddr;
+ struct eth_hdr *ethhdr;
+ struct etharp_hdr *hdr;
+ struct pbuf *p;
+ u8_t i;
+
+ srcaddr = (struct eth_addr *)netif->hwaddr;
+
+ /* Make room for Ethernet header. */
+ if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
+ /* The pbuf_header() call shouldn't fail, and we'll just bail
+ out if it does.. */
+ DEBUGF(ETHARP_DEBUG, ("etharp_output: could not allocate room for header.\n"));
+#ifdef LINK_STATS
+ ++stats.link.lenerr;
+#endif /* LINK_STATS */
+ return NULL;
+ }
+
+
+ dest = NULL;
+ /* Construct Ethernet header. Start with looking up deciding which
+ MAC address to use as a destination address. Broadcasts and
+ multicasts are special, all other addresses are looked up in the
+ ARP table. */
+ if(ip_addr_isany(ipaddr) ||
+ ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
+ dest = (struct eth_addr *)ðbroadcast;
+ } else if(ip_addr_ismulticast(ipaddr)) {
+ /* Hash IP multicast address to MAC address. */
+ mcastaddr.addr[0] = 0x01;
+ mcastaddr.addr[1] = 0x0;
+ mcastaddr.addr[2] = 0x5e;
+ mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
+ mcastaddr.addr[4] = ip4_addr3(ipaddr);
+ mcastaddr.addr[5] = ip4_addr4(ipaddr);
+ dest = &mcastaddr;
+ } else {
+ if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
+ /* Use the IP address of the default gateway if the destination
+ is on the same subnet as we are. */
+ ipaddr = &(netif->gw);
+ }
+
+ /* We try to find a stable mapping. */
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ if(arp_table[i].state == ETHARP_STATE_STABLE &&
+ ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
+ dest = &arp_table[i].ethaddr;
+ break;
+ }
+ }
+ }
+
+ if(dest == NULL) {
+ /* No destination address has been found, so we'll have to send
+ out an ARP request for the IP address. The outgoing packet is
+ queued unless the queue is full. */
+
+ /* We check if we are already querying for this address. If so,
+ we'll bail out. */
+ for(i = 0; i < ARP_TABLE_SIZE; ++i) {
+ if(arp_table[i].state == ETHARP_STATE_PENDING &&
+ ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
+ DEBUGF(ETHARP_DEBUG, ("etharp_output: already queued\n"));
+ return NULL;
+ }
+ }
+
+ i = find_arp_entry();
+
+ /* If all table entries were in pending state, we won't send out any
+ more ARP requests. We'll just give up. */
+ if(i == ARP_TABLE_SIZE) {
+ return NULL;
+ }
+
+ /* Now, i is the ARP table entry which we will fill with the new
+ information. */
+ ip_addr_set(&arp_table[i].ipaddr, ipaddr);
+ /* for(k = 0; k < 6; ++k) {
+ arp_table[i].ethaddr.addr[k] = dest->addr[k];
+ }*/
+ arp_table[i].ctime = ctime;
+ arp_table[i].state = ETHARP_STATE_PENDING;
+#if 1
+ arp_table[i].p = q;
+ arp_table[i].payload = q->payload;
+ arp_table[i].len = q->len;
+ arp_table[i].tot_len = q->tot_len;
+
+ /* Because the pbuf will be queued, we'll increase the refernce
+ count. */
+ DEBUGF(ETHARP_DEBUG, ("etharp_output: queueing %p\n", q));
+ pbuf_ref(q);
+#else
+ arp_table[i].p = NULL;
+#endif /* 0 */
+
+
+ /* We allocate a pbuf for the outgoing ARP request packet. */
+ p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
+ if(p == NULL) {
+ /* No ARP request packet could be allocated, so we forget about
+ the ARP table entry. */
+ if(i != ARP_TABLE_SIZE) {
+ arp_table[i].state = ETHARP_STATE_EMPTY;
+ /* We decrease the reference count of the queued pbuf (which now
+ is dequeued). */
+ DEBUGF(ETHARP_DEBUG, ("etharp_output: couldn't alloc pbuf for query, dequeueing %p\n", q));
+ pbuf_free(q);
+ }
+ return NULL;
+ }
+
+ hdr = p->payload;
+
+ hdr->opcode = htons(ARP_REQUEST);
+
+ for(i = 0; i < 6; ++i) {
+ hdr->dhwaddr.addr[i] = 0x00;
+ hdr->shwaddr.addr[i] = srcaddr->addr[i];
+ }
+
+ ip_addr_set(&(hdr->dipaddr), ipaddr);
+ ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
+
+ hdr->hwtype = htons(HWTYPE_ETHERNET);
+ ARPH_HWLEN_SET(hdr, 6);
+
+ hdr->proto = htons(ETHTYPE_IP);
+ ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
+
+ for(i = 0; i < 6; ++i) {
+ hdr->ethhdr.dest.addr[i] = 0xff;
+ hdr->ethhdr.src.addr[i] = srcaddr->addr[i];
+ }
+
+ hdr->ethhdr.type = htons(ETHTYPE_ARP);
+ return p;
+ } else {
+ /* A valid IP->MAC address mapping was found, so we construct the
+ Ethernet header for the outgoing packet. */
+
+ ethhdr = q->payload;
+
+ for(i = 0; i < 6; i++) {
+ ethhdr->dest.addr[i] = dest->addr[i];
+ ethhdr->src.addr[i] = srcaddr->addr[i];
+ }
+
+ ethhdr->type = htons(ETHTYPE_IP);
+
+ return q;
+ }
+
+
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/netif/ethernetif.c b/src/netif/ethernetif.c
new file mode 100644
index 0000000..96117b4
--- /dev/null
+++ b/src/netif/ethernetif.c
@@ -0,0 +1,344 @@
+/*
+ * 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>
+ *
+ */
+
+/*
+ * 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 "lwip/debug.h"
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include "netif/arp.h"
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 't'
+
+struct ethernetif {
+ struct eth_addr *ethaddr;
+ /* Add whatever per-interface state that is needed here. */
+};
+
+static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+
+/* Forward declarations. */
+static void ethernetif_input(struct netif *netif);
+static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+/*-----------------------------------------------------------------------------------*/
+static void
+low_level_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+
+ ethernetif = netif->state;
+
+ /* Obtain MAC address from network interface. */
+ ethernetif->ethaddr->addr[0] = ;
+ ethernetif->ethaddr->addr[1] = ;
+ ethernetif->ethaddr->addr[2] = ;
+
+ /* Do whatever else is needed to initialize interface. */
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * 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 ethernetif *ethernetif, struct pbuf *p)
+{
+ struct pbuf *q;
+
+ initiate transfer();
+
+ 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);
+ }
+
+ signal that packet should be sent();
+
+#ifdef LINK_STATS
+ stats.link.xmit++;
+#endif /* LINK_STATS */
+
+ 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 ethernetif *ethernetif)
+{
+ struct pbuf *p, *q;
+ u16_t len;
+
+ /* Obtain the size of the packet and put it into the "len"
+ variable. */
+ len = ;
+
+ /* 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. */
+ 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);
+ }
+ acknowledge that packet has been read();
+#ifdef LINK_STATS
+ stats.link.recv++;
+#endif /* LINK_STATS */
+ } else {
+ drop packet();
+#ifdef LINK_STATS
+ stats.link.memerr++;
+ stats.link.drop++;
+#endif /* LINK_STATS */
+ }
+
+ return p;
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * ethernetif_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
+ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+ struct ethernetif *ethernetif;
+ struct pbuf *q;
+ struct eth_hdr *ethhdr;
+ struct eth_addr *dest, mcastaddr;
+ struct ip_addr *queryaddr;
+ err_t err;
+ u8_t i;
+
+ ethernetif = netif->state;
+
+ /* Make room for Ethernet header. */
+ if(pbuf_header(p, 14) != 0) {
+ /* The pbuf_header() call shouldn't fail, but we allocate an extra
+ pbuf just in case. */
+ q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
+ if(q == NULL) {
+#ifdef LINK_STATS
+ stats.link.drop++;
+ stats.link.memerr++;
+#endif /* LINK_STATS */
+ return ERR_MEM;
+ }
+ pbuf_chain(q, p);
+ p = q;
+ }
+
+ /* Construct Ethernet header. Start with looking up deciding which
+ MAC address to use as a destination address. Broadcasts and
+ multicasts are special, all other addresses are looked up in the
+ ARP table. */
+ queryaddr = ipaddr;
+ if(ip_addr_isany(ipaddr) ||
+ ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
+ dest = (struct eth_addr *)ðbroadcast;
+ } else if(ip_addr_ismulticast(ipaddr)) {
+ /* Hash IP multicast address to MAC address. */
+ mcastaddr.addr[0] = 0x01;
+ mcastaddr.addr[1] = 0x0;
+ mcastaddr.addr[2] = 0x5e;
+ mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
+ mcastaddr.addr[4] = ip4_addr3(ipaddr);
+ mcastaddr.addr[5] = ip4_addr4(ipaddr);
+ dest = &mcastaddr;
+ } else {
+
+ if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
+ /* Use destination IP address if the destination is on the same
+ subnet as we are. */
+ queryaddr = ipaddr;
+ } else {
+ /* Otherwise we use the default router as the address to send
+ the Ethernet frame to. */
+ queryaddr = &(netif->gw);
+ }
+ dest = arp_lookup(queryaddr);
+ }
+
+
+ /* If the arp_lookup() didn't find an address, we send out an ARP
+ query for the IP address. */
+ if(dest == NULL) {
+ q = arp_query(netif, ethernetif->ethaddr, queryaddr);
+ if(q != NULL) {
+ err = low_level_output(ethernetif, q);
+ pbuf_free(q);
+ return err;
+ }
+#ifdef LINK_STATS
+ stats.link.drop++;
+ stats.link.memerr++;
+#endif /* LINK_STATS */
+ return ERR_MEM;
+ }
+ ethhdr = p->payload;
+
+ for(i = 0; i < 6; i++) {
+ ethhdr->dest.addr[i] = dest->addr[i];
+ ethhdr->src.addr[i] = ethernetif->ethaddr->addr[i];
+ }
+
+ ethhdr->type = htons(ETHTYPE_IP);
+
+ return low_level_output(ethernetif, p);
+
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * ethernetif_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
+ethernetif_input(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+ struct eth_hdr *ethhdr;
+ struct pbuf *p;
+
+
+ ethernetif = netif->state;
+
+ p = low_level_input(ethernetif);
+
+ if(p != NULL) {
+
+#ifdef LINK_STATS
+ stats.link.recv++;
+#endif /* LINK_STATS */
+
+ ethhdr = p->payload;
+
+ switch(htons(ethhdr->type)) {
+ case ETHTYPE_IP:
+ arp_ip_input(netif, p);
+ pbuf_header(p, -14);
+ netif->input(p, netif);
+ break;
+ case ETHTYPE_ARP:
+ p = arp_arp_input(netif, ethernetif->ethaddr, p);
+ if(p != NULL) {
+ low_level_output(ethernetif, p);
+ pbuf_free(p);
+ }
+ break;
+ default:
+ pbuf_free(p);
+ break;
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+arp_timer(void *arg)
+{
+ arp_tmr();
+ sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
+/*
+ * ethernetif_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
+ethernetif_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+
+ ethernetif = mem_malloc(sizeof(struct ethernetif));
+ netif->state = ethernetif;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = ethernetif_output;
+ netif->linkoutput = low_level_output;
+
+ ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
+
+ low_level_init(netif);
+ arp_init();
+
+ sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/src/netif/loopif.c b/src/netif/loopif.c
new file mode 100644
index 0000000..e46b7a8
--- /dev/null
+++ b/src/netif/loopif.c
@@ -0,0 +1,81 @@
+/*
+ * 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/opt.h"
+#include "netif/loopif.h"
+#include "netif/tcpdump.h"
+
+#include "lwip/tcp.h"
+#include "lwip/ip.h"
+
+/*-----------------------------------------------------------------------------------*/
+static err_t
+loopif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+ struct pbuf *q, *r;
+ char *ptr;
+
+#ifdef LWIP_DEBUG
+ tcpdump(p);
+#endif /* LWIP_DEBUG */
+
+ r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+ if(r != NULL) {
+ ptr = r->payload;
+
+ for(q = p; q != NULL; q = q->next) {
+ bcopy(q->payload, ptr, q->len);
+ ptr += q->len;
+ }
+ netif->input(r, netif);
+ return ERR_OK;
+ }
+ return ERR_MEM;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+loopif_init(struct netif *netif)
+{
+ netif->name[0] = 'l';
+ netif->name[1] = 'o';
+ netif->output = loopif_output;
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+
+
+
+
diff --git a/src/netif/tcpdump.c b/src/netif/tcpdump.c
new file mode 100644
index 0000000..4db8cce
--- /dev/null
+++ b/src/netif/tcpdump.c
@@ -0,0 +1,186 @@
+/*
+ * 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 <stdio.h>
+
+#include "netif/tcpdump.h"
+#include "lwip/ip.h"
+#include "lwip/tcp.h"
+#include "lwip/udp.h"
+#include "lwip/inet.h"
+
+static FILE *file = NULL;
+
+/*-----------------------------------------------------------------------------------*/
+void
+tcpdump_init(void)
+{
+ char *fname;
+
+ fname = "/tmp/tcpdump";
+ file = fopen(fname, "w");
+ if(file == NULL) {
+ perror("tcpdump_init: fopen");
+ }
+ DEBUGF(TCPDUMP_DEBUG, ("tcpdump: file %s\n", fname));
+}
+/*-----------------------------------------------------------------------------------*/
+void
+tcpdump(struct pbuf *p)
+{
+ struct ip_hdr *iphdr;
+ struct tcp_hdr *tcphdr;
+ struct udp_hdr *udphdr;
+ char flags[5];
+ int i;
+ int len;
+ int offset;
+
+ if(file == NULL) {
+ return;
+ }
+#ifdef IPv4
+ iphdr = p->payload;
+ switch(IPH_PROTO(iphdr)) {
+ case IP_PROTO_TCP:
+ tcphdr = (struct tcp_hdr *)((char *)iphdr + IP_HLEN);
+
+ pbuf_header(p, -IP_HLEN);
+ if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len) != 0) {
+ DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n"));
+ /* fprintf(file, "chksum 0x%lx ", tcphdr->chksum);
+ tcphdr->chksum = 0;
+ fprintf(file, "should be 0x%lx ", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len));*/
+ fprintf(file, "!chksum ");
+ }
+
+ i = 0;
+ if(TCPH_FLAGS(tcphdr) & TCP_SYN) {
+ flags[i++] = 'S';
+ }
+ if(TCPH_FLAGS(tcphdr) & TCP_PSH) {
+ flags[i++] = 'P';
+ }
+ if(TCPH_FLAGS(tcphdr) & TCP_FIN) {
+ flags[i++] = 'F';
+ }
+ if(TCPH_FLAGS(tcphdr) & TCP_RST) {
+ flags[i++] = 'R';
+ }
+ if(i == 0) {
+ flags[i++] = '.';
+ }
+ flags[i++] = 0;
+
+
+
+ fprintf(file, "%d.%d.%d.%d.%u > %d.%d.%d.%d.%u: ",
+ (int)(ntohl(iphdr->src.addr) >> 24) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 16) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 8) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 0) & 0xff,
+ ntohs(tcphdr->src),
+ (int)(ntohl(iphdr->dest.addr) >> 24) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 16) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 8) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 0) & 0xff,
+ ntohs(tcphdr->dest));
+ offset = TCPH_OFFSET(tcphdr) >> 4;
+
+ len = ntohs(IPH_LEN(iphdr)) - offset * 4 - IP_HLEN;
+ if(len != 0 || flags[0] != '.') {
+ fprintf(file, "%s %lu:%lu(%u) ",
+ flags,
+ ntohl(tcphdr->seqno),
+ ntohl(tcphdr->seqno) + len,
+ len);
+ }
+ if(TCPH_FLAGS(tcphdr) & TCP_ACK) {
+ fprintf(file, "ack %lu ",
+ ntohl(tcphdr->ackno));
+ }
+ fprintf(file, "wnd %u\n",
+ ntohs(tcphdr->wnd));
+
+ fflush(file);
+
+ pbuf_header(p, IP_HLEN);
+ break;
+
+ case IP_PROTO_UDP:
+ udphdr = (struct udp_hdr *)((char *)iphdr + IP_HLEN);
+
+ pbuf_header(p, -IP_HLEN);
+ if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_UDP, p->tot_len) != 0) {
+ DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n"));
+ /* fprintf(file, "chksum 0x%lx ", tcphdr->chksum);
+ tcphdr->chksum = 0;
+ fprintf(file, "should be 0x%lx ", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
+ (struct ip_addr *)&(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len));*/
+ fprintf(file, "!chksum ");
+ }
+
+ fprintf(file, "%d.%d.%d.%d.%u > %d.%d.%d.%d.%u: ",
+ (int)(ntohl(iphdr->src.addr) >> 24) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 16) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 8) & 0xff,
+ (int)(ntohl(iphdr->src.addr) >> 0) & 0xff,
+ ntohs(udphdr->src),
+ (int)(ntohl(iphdr->dest.addr) >> 24) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 16) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 8) & 0xff,
+ (int)(ntohl(iphdr->dest.addr) >> 0) & 0xff,
+ ntohs(udphdr->dest));
+ fprintf(file, "U ");
+ len = ntohs(IPH_LEN(iphdr)) - sizeof(struct udp_hdr) - IP_HLEN;
+ fprintf(file, " %d\n", len);
+
+ fflush(file);
+
+ pbuf_header(p, IP_HLEN);
+ break;
+
+ }
+#endif /* IPv4 */
+}
+/*-----------------------------------------------------------------------------------*/
+
+
+
+