Hi,

  Is there anyone having success on using loopif in a multi-threaded
application?  The attached is a modified unix/proj/unixsim/simhost.c.
Basically it is a self-contained server/client which binds/connects to
127.0.0.2 through loopif.

  The problem is that this program failed to run indefinitely and hung
after a few client <-> server transactions(lwIP CVS version, with
LWIP_HAVE_LOOPIF = 1, running on FreeBSD-CURRENT):

freebsd> ./simhost -d
Host at 127.0.0.2 mask 255.0.0.0 gateway 127.0.0.1
System initialized.
TCP/IP initialized.
netif_set_ipaddr: netif address being changed
netif: IP address of interface API message 0x8065a28
cli connecting...
tcpip_thread: API message 0x8065a28
tcp_bind: bind to port 80
tcpip_thread: API message 0x8065a3c
tcp_connect to port 80
tcp_enqueue(pcb=0x8065300, arg=0x0, len=0, flags=2, copy=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6509:6510 (0x2)
tcp_enqueue: 1 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6509, ack 6509
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6509, ack 6509, i 0
tcp_output_segment: rtseq 6509
tcp_output_segment: 6509:6509
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        0      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc7     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcpip_thread: API message 0x8065a3c
srv listening return, proceed to accept
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (0x0)
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, seg == NULL, ack 6509
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: rtime 6 pcb->rto 6
tcp_slowtmr: cwnd 1024 ssthresh 2048
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 0, seq 6509, ack 6509
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 0, seq 6509, ack 6509, i 0
tcp_output_segment: rtseq 6509
tcp_output_segment: 6509:6509
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        1      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc6     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcpip_thread: IP packet 0x8065a3c
ip_input: iphdr->dest 0x200007f netif->ip_addr 0x200007f (0x7f, 0x7f, 0x2000000)
ip_input: packet accepted on interface lo
ip_input: IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        1      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc6     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
ip_input: p->len 44 p->tot_len 44
TCP header:
+-------------------------------+
|     4097      |       80      | (src port, dest port)
+-------------------------------+
|           0000006509          | (seq no)
+-------------------------------+
|           0000000000          | (ack no)
+-------------------------------+
|  6 |   |000010|      8096     | (hdrlen, flags (SYN ), win)
+-------------------------------+
|    0x5278     |         0     | (chksum, urgp)
+-------------------------------+
tcp_input: packed for LISTENing connection.
TCP connection request 4097 -> 80.
tcp_enqueue(pcb=0x80653a4, arg=0x0, len=0, flags=12, copy=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6516:6517 (0x12)
tcp_enqueue: 1 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6516, ack 6516
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6516, ack 6516, i 0
tcp_output_segment: rtseq 6516
tcp_output_segment: 6516:6516
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        2      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc5     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcpip_thread: IP packet 0x8065a3c
ip_input: iphdr->dest 0x200007f netif->ip_addr 0x200007f (0x7f, 0x7f, 0x2000000)
ip_input: packet accepted on interface lo
ip_input: IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        2      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc5     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
ip_input: p->len 44 p->tot_len 44
TCP header:
+-------------------------------+
|       80      |     4097      | (src port, dest port)
+-------------------------------+
|           0000006516          | (seq no)
+-------------------------------+
|           0000006510          | (ack no)
+-------------------------------+
|  6 |   |010010|      8096     | (hdrlen, flags (SYN ACK ), win)
+-------------------------------+
|    0x38f3     |         0     | (chksum, urgp)
+-------------------------------+
+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags SYN ACK 
-+-+-+-+-+-+-+-+-+-+-+-+-+-+
State: SYN_SENT
SYN-SENT: ackno 6510 pcb->snd_nxt 6510 unacked 6509
tcp_process: SYN-SENT --queuelen 0
tcp_output: nothing to send (0x0)
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, seg == NULL, ack 6510
State: ESTABLISHED
cli writing HTTP request....
netconn_write: writing 29 bytes (0)
tcpip_thread: API message 0x8065a3c
tcp_write(pcb=0x8065300, arg=0x80623f0, len=29, copy=0)
tcp_enqueue(pcb=0x8065300, arg=0x80623f0, len=29, flags=0, copy=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6510:6539 (0x0)
tcp_enqueue: 2 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 29, seq 6510, ack 6510
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 29, seq 6510, ack 6510, i 0
tcp_output_segment: 6510:6539
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        69     | (v, hl, tos, len)
+-------------------------------+
|        3      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dab     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()cli deleting connection
tcpip_thread: API message 0x8065a3c
tcp_close: closing in State: ESTABLISHED
tcp_enqueue(pcb=0x8065300, arg=0x0, len=0, flags=1, copy=1)
tcp_enqueue: queuelen: 2
tcp_enqueue: queueing 6539:6540 (0x1)
tcp_enqueue: 3 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 29, seq 6539, ack 6510
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 29, seq 6539, ack 6510, i 0
tcp_output_segment: 6539:6539
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        40     | (v, hl, tos, len)
+-------------------------------+
|        4      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc7     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcpip_thread: IP packet 0x8065a3c
ip_input: iphdr->dest 0x200007f netif->ip_addr 0x200007f (0x7f, 0x7f, 0x2000000)
ip_input: packet accepted on interface lo
ip_input: IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        69     | (v, hl, tos, len)
+-------------------------------+
|        3      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dab     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
ip_input: p->len 69 p->tot_len 69
TCP header:
+-------------------------------+
|     4097      |       80      | (src port, dest port)
+-------------------------------+
|           0000006510          | (seq no)
+-------------------------------+
|           0000006517          | (ack no)
+-------------------------------+
|  5 |   |011000|      8096     | (hdrlen, flags (PSH ACK ), win)
+-------------------------------+
|    0x8d1b     |         0     | (chksum, urgp)
+-------------------------------+
+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags PSH ACK 
-+-+-+-+-+-+-+-+-+-+-+-+-+-+
State: SYN_RCVD
TCP connection established 4097 -> 80.
State: ESTABLISHED
tcp_receive: window update 8096
tcp_receive: slow start cwnd 1025
tcp_receive: ACK for 6517, unacked->seqno 6516:6517
tcp_receive: removing 6516:6517 from pcb->unacked
tcp_receive: queuelen 1 ... 0 (after freeing unacked)
tcp_receive: pcb->rttest 6 rtseq 6516 ackno 6517
tcp_receive: experienced rtt 0 ticks (0 msec).
tcp_receive: RTO 5 (2500 milliseconds)
tcp_output: nothing to send (0x0)
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, seg == NULL, ack 6517
State: ESTABLISHED
cli (re)creating connection...
srv receiving HTTP request ....
tcpip_thread: API message 0x8065a3c
tcpip_thread: API message 0x8065a28
tcp_output: sending ACK for 6539
ip_output_if: lo0
IP header:
+-------------------------------+
cli connecting...
| 4 | 5 |  0x00 |        40     | (v, hl, tos, len)
+-------------------------------+
|        5      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc6     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcp_recved: recveived 29 bytes, wnd 8096 (0).
tcpip_thread: API message 0x8065a3c
tcp_connect to port 80
tcp_enqueue(pcb=0x806525c, arg=0x0, len=0, flags=2, copy=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6527:6528 (0x2)
tcp_enqueue: 1 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6527, ack 6527
tcp_output: snd_wnd 8096, cwnd 1, wnd 1, effwnd 0, seq 6527, ack 6527, i 0
tcp_output_segment: rtseq 6527
tcp_output_segment: 6527:6527
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        44     | (v, hl, tos, len)
+-------------------------------+
|        6      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc1     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()netconn_recv: received 0x806571c (err 0)
srv: it's a GET method GET /index.html HTTP/1.0


srv delete server connection
tcpip_thread: API message 0x8065a3c
tcp_close: closing in State: ESTABLISHED
tcp_enqueue(pcb=0x80653a4, arg=0x0, len=0, flags=1, copy=1)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6517:6518 (0x1)
tcp_enqueue: 1 (after enqueued)
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 0, seq 6517, ack 6517
tcp_output: snd_wnd 8096, cwnd 1024, wnd 1024, effwnd 0, seq 6517, ack 6517, i 0
tcp_output_segment: rtseq 6517
tcp_output_segment: 6517:6517
ip_output_if: lo0
IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        40     | (v, hl, tos, len)
+-------------------------------+
|        7      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc4     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
netif->output()tcpip_thread: IP packet 0x8065a3c
ip_input: iphdr->dest 0x200007f netif->ip_addr 0x200007f (0x7f, 0x7f, 0x2000000)
ip_input: packet accepted on interface lo
ip_input: IP header:
+-------------------------------+
| 4 | 5 |  0x00 |        40     | (v, hl, tos, len)
+-------------------------------+
|        5      |010|       0   | (id, flags, offset)
+-------------------------------+
|  255  |    6  |    0x7dc6     | (ttl, proto, chksum)
+-------------------------------+
|  127  |    0  |    0  |    2  | (src)
+-------------------------------+
|  127  |    0  |    0  |    2  | (dest)
+-------------------------------+
ip_input: p->len 40 p->tot_len 40
TCP header:
+-------------------------------+
|       80      |     4097      | (src port, dest port)
+-------------------------------+
|           0000006517          | (seq no)
+-------------------------------+
|           0000006539          | (ack no)
+-------------------------------+
|  5 |   |010000|      8096     | (hdrlen, flags (ACK ), win)
+-------------------------------+
|    0x4edf     |         0     | (chksum, urgp)
+-------------------------------+
+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ACK -+-+-+-+-+-+-+-+-+-+-+-+-+-+
State: FIN_WAIT_1
tcp_receive: window update 8096
tcp_receive: slow start cwnd 2048
tcp_receive: ACK for 6539, unacked->seqno 6510:6539
tcp_receive: removing 6510:6539 from pcb->unacked
tcp_receive: queuelen 3 ... 1 (after freeing unacked)
tcp_receive: pcb->rttest 6 rtseq 6509 ackno 6539
tcp_receive: experienced rtt 0 ticks (0 msec).
tcp_receive: RTO 5 (2500 milliseconds)
tcp_output: nothing to send (0x0)
tcp_output: snd_wnd 8096, cwnd 2048, wnd 2048, seg == NULL, ack 6539
State: FIN_WAIT_1
srv listening return, proceed to accept
[...hanging...]
/*
 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. All rights
 * reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer. 2. Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other
 * materials provided with the distribution. 3. The name of the author may
 * not be used to endorse or promote products derived from this software
 * without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * This file is part of the lwIP TCP/IP stack.
 * 
 * Author: Adam Dunkels <[EMAIL PROTECTED]>
 * 
 */

#include <unistd.h>
#include <fcntl.h>
#include <getopt.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"

#if PPP_SUPPORT
#include "netif/ppp/ppp.h"
#define PPP_PTY_TEST 1
#include <termios.h>
#endif

#include "lwip/ip_addr.h"
#include "arch/perf.h"

#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"

#if LWIP_RAW
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/sockets.h"
#endif

/* (manual) host IP configuration */
static struct ip_addr ipaddr, netmask, gw;

/* ping out destination cmd option */
static unsigned char ping_flag;
static struct ip_addr ping_addr;

/* nonstatic debug cmd option, exported in lwipopts.h */
unsigned char   debug_flags;

/** @todo add options for selecting netif, starting DHCP client etc */
static struct option longopts[] = {
        /* turn on debugging output (if build with LWIP_DEBUG) */
        {"debug", no_argument, NULL, 'd'},
        /* help */
        {"help", no_argument, NULL, 'h'},
        /* gateway address */
        {"gateway", required_argument, NULL, 'g'},
        /* ip address */
        {"ipaddr", required_argument, NULL, 'i'},
        /* netmask */
        {"netmask", required_argument, NULL, 'm'},
        /* ping destination */
        {"ping", required_argument, NULL, 'p'},
        /* new command line options go here! */
        {NULL, 0, NULL, 0}
};
#define NUM_OPTS ((sizeof(longopts) / sizeof(struct option)) - 1)

void 
usage(void)
{
        unsigned char   i;

        printf("options:\n");
        for (i = 0; i < NUM_OPTS; i++) {
                printf("-%c --%s\n", longopts[i].val, longopts[i].name);
        }
}

static void
tcp_debug_timeout(void *data)
{
#if TCP_DEBUG
        tcp_debug_print_pcbs();
#endif                          /* TCP_DEBUG */
        sys_timeout(5000, tcp_debug_timeout, NULL);
}

static void
tcpip_init_done(void *arg)
{
        sys_sem_t      *sem;
        sem = arg;
        sys_sem_signal(*sem);
}

#if PPP_SUPPORT
void
pppLinkStatusCallback(void *ctx, int errCode, void *arg)
{
        switch (errCode) {
                case PPPERR_NONE:       /* No error. */
                {
                        struct ppp_addrs *ppp_addrs = arg;

                        printf("pppLinkStatusCallback: PPPERR_NONE");
                        printf(" our_ipaddr=%s", 
_inet_ntoa(ppp_addrs->our_ipaddr.addr));
                        printf(" his_ipaddr=%s", 
_inet_ntoa(ppp_addrs->his_ipaddr.addr));
                        printf(" netmask=%s", 
_inet_ntoa(ppp_addrs->netmask.addr));
                        printf(" dns1=%s", _inet_ntoa(ppp_addrs->dns1.addr));
                        printf(" dns2=%s\n", _inet_ntoa(ppp_addrs->dns2.addr));
                }
                break;

        case PPPERR_PARAM:      /* Invalid parameter. */
                printf("pppLinkStatusCallback: PPPERR_PARAM\n");
                break;

        case PPPERR_OPEN:       /* Unable to open PPP session. */
                printf("pppLinkStatusCallback: PPPERR_OPEN\n");
                break;

        case PPPERR_DEVICE:     /* Invalid I/O device for PPP. */
                printf("pppLinkStatusCallback: PPPERR_DEVICE\n");
                break;

        case PPPERR_ALLOC:      /* Unable to allocate resources. */
                printf("pppLinkStatusCallback: PPPERR_ALLOC\n");
                break;

        case PPPERR_USER:       /* User interrupt. */
                printf("pppLinkStatusCallback: PPPERR_USER\n");
                break;

        case PPPERR_CONNECT:    /* Connection lost. */
                printf("pppLinkStatusCallback: PPPERR_CONNECT\n");
                break;

        case PPPERR_AUTHFAIL:   /* Failed authentication challenge. */
                printf("pppLinkStatusCallback: PPPERR_AUTHFAIL\n");
                break;

        case PPPERR_PROTOCOL:   /* Failed to meet protocol. */
                printf("pppLinkStatusCallback: PPPERR_PROTOCOL\n");
                break;

        default:
                printf("pppLinkStatusCallback: unknown errCode %d\n", errCode);
                break;
        }
}
#endif

/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_RAW

static int      seq_num;

#if 0
/* Ping using the raw ip */
static int
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr)
{
        printf("ping recv\n");
        return 1;               /* eat the event */
}

static void
ping_send(struct raw_pcb *raw, struct ip_addr *addr)
{
        struct pbuf    *p;
        struct icmp_echo_hdr *iecho;

        p = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr), PBUF_RAM);
        if (!p)
                return;

        iecho = p->payload;
        ICMPH_TYPE_SET(iecho, ICMP_ECHO);
        iecho->chksum = 0;
        iecho->seqno = htons(seq_num);

        iecho->chksum = inet_chksum(iecho, p->len);
        raw_send_to(raw, p, addr);

        pbuf_free(p);

        seq_num++;
}

static void
ping_thread(void *arg)
{
        struct raw_pcb *raw;

        if (!(raw = raw_new(IP_PROTO_ICMP)))
                return;

        raw_recv(raw, ping_recv, NULL);

        while (1) {
                printf("ping send\n");
                ping_send(raw, &ping_addr);
                sleep(1);
        }
        /* Never reaches this */
        raw_remove(raw);
}
#else
/* Ping using the socket ip */

static void
ping_send(int s, struct ip_addr *addr)
{
        struct icmp_echo_hdr *iecho;
        struct sockaddr_in to;

        if (!(iecho = malloc(sizeof(struct icmp_echo_hdr))))
                return;

        ICMPH_TYPE_SET(iecho, ICMP_ECHO);
        iecho->chksum = 0;
        iecho->seqno = htons(seq_num);
        iecho->chksum = inet_chksum(iecho, sizeof(*iecho));

        to.sin_len = sizeof(to);
        to.sin_family = AF_INET;
        to.sin_addr.s_addr = addr->addr;

        lwip_sendto(s, iecho, sizeof(*iecho), 0, (struct sockaddr *)&to, 
sizeof(to));

        free(iecho);
        seq_num++;
}

static void
ping_recv(int s, struct ip_addr *addr)
{
        char            buf       [200];
        int             fromlen   , len;
        struct sockaddr_in from;

        len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, 
&fromlen);

        printf("Received %d bytes from %lx\n", len, 
ntohl(from.sin_addr.s_addr));
}

static void
ping_thread(void *arg)
{
        int             s;

        if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
                return;
        }
        while (1) {
                printf("sending ping\n");
                ping_send(s, &ping_addr);
                ping_recv(s, &ping_addr);
                sleep(1);
        }
}
#endif

#endif

static void
cli_thread(void *arg)
{
        struct netconn *cliConn;
        struct ip_addr  srvAddr;
        static char     pageBuf[] = "GET /index.html HTTP/1.0\r\n\r\n";
        size_t          len = sizeof(pageBuf);
        struct netbuf  *nb;
        char           *data;
        int             xlen;
        int             err;

        printf("cli thread activated\n");

        for (;;) {
                printf("cli (re)creating connection...\n");
                if ((cliConn = netconn_new(NETCONN_TCP)) == NULL) {
                        printf("netconn_new failed\n");
                        return; /* should not happen */
                }
                IP4_ADDR(&srvAddr, 127, 0, 0, 2);
                printf("cli connecting...\n");
                while ((err = netconn_connect(cliConn, &srvAddr, 80)) != 0) {
                        printf("connection error %d\n", err);
                }
                printf("cli writing HTTP request....\n");
                if (netconn_write(cliConn, pageBuf, len, NETCONN_NOCOPY) != 
ERR_OK) {
                        printf("netconn_write FAILED!\n");
                        netconn_close(cliConn);
                        break;
                }
#if     0
                if ((nb = netconn_recv(cliConn)) != NULL) {
                        netbuf_data(nb, (void *)&data, (u16_t *) &xlen);
                        printf("got respond %s\n", data);
                        netbuf_delete(nb);
                }
#endif
//              sleep(1);
                netconn_delete(cliConn);
        }
        printf("client thread terminated\n");
}

static void
srv_thread(void *arg)
{
        struct netconn *srvConn, *nc;
        struct netbuf  *nb;
        struct ip_addr  myAddr;
        char           *data;
        size_t          len;
        int             err;

        printf("srv thread activated\n");
        if ((srvConn = netconn_new(NETCONN_TCP)) == NULL)
                return;         /* should not happen */
        if ((err = netconn_bind(srvConn, NULL, 80)) != 0)
                printf("bind failed, err = %d\n", err);
        if ((err = netconn_listen(srvConn)) != 0)
                printf("listen failed, err = %d\n", err);
        for (;;) {
                printf("srv listening return, proceed to accept\n");
                nc = netconn_accept(srvConn);
                if (nc == NULL) {
                        printf("srv accept failed!\n");
                        continue;
                }
                printf("srv receiving HTTP request ....\n");
                if ((nb = netconn_recv(nc)) != NULL) {
                        netbuf_data(nb, (void *)&data, (u16_t *) & len);

                        if (data[0] == 'G' && data[1] == 'E' && data[2] == 'T') 
{
                                printf("srv: it's a GET method %s\n", data);
#if     0
                                if (netconn_write(nc, "test", 5, 
NETCONN_NOCOPY) != ERR_OK) {
                                        printf("netconn_write FAILED!\n");
                                        netconn_close(nc);
                                }
#endif
                        }
                        netbuf_delete(nb);
                }
                printf("srv delete server connection\n");
                while (netconn_delete(nc) != ERR_OK) {
                        printf("srv netconn_delete failed!\n");
                        sleep(3);
                }
        }
        printf("server thread terminated\n");
}

struct netif    netif;
#if LWIP_HAVE_LOOPIF
struct netif    loopif;
#endif
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
        sys_sem_t       sem;
#if PPP_SUPPORT
        sio_fd_t        ppp_sio;
#endif

        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 PPP_SUPPORT
        pppInit();
#if PPP_PTY_TEST
        ppp_sio = sio_open(2);
#else
        ppp_sio = sio_open(0);
#endif
        if (!ppp_sio) {
                perror("Error opening device: ");
                exit(1);
        }
#ifdef LWIP_PPP_CHAP_TEST
        pppSetAuth(PPPAUTHTYPE_CHAP, "lwip", "mysecret");
#endif

        pppOpen(ppp_sio, pppLinkStatusCallback, NULL);
#endif                          /* PPP_SUPPORT */

#if LWIP_DHCP
        {
                IP4_ADDR(&gw, 0, 0, 0, 0);
                IP4_ADDR(&ipaddr, 0, 0, 0, 0);
                IP4_ADDR(&netmask, 0, 0, 0, 0);

                netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tapif_init,
                          tcpip_input);
                netif_set_default(&netif);
                dhcp_start(&netif);
        }
#else

#if LWIP_HAVE_LOOPIF == 0
        netif_set_default(netif_add(&netif, &ipaddr, &netmask, &gw, NULL, 
tapif_init,
                                    tcpip_input));
        netif_set_up(&netif);
#endif

#endif

#if 0
        /* Only used for testing purposes: */
        netif_add(&ipaddr, &netmask, &gw, NULL, pcapif_init, tcpip_input);
#endif

#if LWIP_HAVE_LOOPIF
        IP4_ADDR(&gw, 127, 0, 0, 1);
        IP4_ADDR(&ipaddr, 127, 0, 0, 2);
        IP4_ADDR(&netmask, 255, 0, 0, 0);

        netif_set_default(netif_add(&loopif, &ipaddr, &netmask, &gw, NULL, 
loopif_init,
                                    tcpip_input));
        netif_set_up(&loopif);
#endif

#if LWIP_TCP
        //tcpecho_init();
        //shell_init();
        //httpd_init();
#endif
#if LWIP_UDP
        //udpecho_init();
#endif

#if LWIP_RAW
        /** @todo remove dependency on RAW PCB support */
        if (ping_flag) {
                sys_thread_new(ping_thread, NULL, DEFAULT_THREAD_PRIO);
        }
#endif
        sys_thread_new(srv_thread, NULL, DEFAULT_THREAD_PRIO);
        sys_thread_new(cli_thread, NULL, DEFAULT_THREAD_PRIO);

        printf("Applications started.\n");

        /* sys_timeout(5000, tcp_debug_timeout, NULL); */

#ifdef MEM_PERF
        mem_perf_init("/tmp/memstats.client");
#endif                          /* MEM_PERF */
#if 0
        stats_display();
#endif
        /* Block for ever. */
        sem = sys_sem_new(0);
        sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
        struct in_addr  inaddr;
        int             ch;
        char            ip_str    [16] = {0}, nm_str[16] = {0}, gw_str[16] = 
{0};

        /* startup defaults (may be overridden by one or more opts) */
        IP4_ADDR(&gw, 127, 0, 0, 1);
        IP4_ADDR(&netmask, 255, 0, 0, 0);
        IP4_ADDR(&ipaddr, 127, 0, 0, 2);

        ping_flag = 0;
        /* use debug flags defined by debug.h */
        debug_flags = DBG_OFF;

        while ((ch = getopt_long(argc, argv, "dhg:i:m:p:", longopts, NULL)) != 
-1) {
                switch (ch) {
                case 'd':
                        debug_flags |= (DBG_ON | DBG_TRACE | DBG_STATE | 
DBG_FRESH | DBG_HALT);
                        break;
                case 'h':
                        usage();
                        exit(0);
                        break;
                case 'g':
                        inet_aton(optarg, &inaddr);
                        gw.addr = inaddr.s_addr;
                        break;
                case 'i':
                        inet_aton(optarg, &inaddr);
                        ipaddr.addr = inaddr.s_addr;
                        break;
                case 'm':
                        inet_aton(optarg, &inaddr);
                        netmask.addr = inaddr.s_addr;
                        break;
                case 'p':
                        ping_flag = !0;
                        inet_aton(optarg, &inaddr);
                        /* lwip inet.h oddity workaround */
                        ping_addr.addr = inaddr.s_addr;
                        strncpy(ip_str, inet_ntoa(inaddr), sizeof(ip_str));
                        printf("Using %s to ping\n", ip_str);
                        break;
                default:
                        usage();
                        break;
                }
        }
        argc -= optind;
        argv += optind;

        inaddr.s_addr = ipaddr.addr;
        strncpy(ip_str, inet_ntoa(inaddr), sizeof(ip_str));
        inaddr.s_addr = netmask.addr;
        strncpy(nm_str, inet_ntoa(inaddr), sizeof(nm_str));
        inaddr.s_addr = gw.addr;
        strncpy(gw_str, inet_ntoa(inaddr), sizeof(gw_str));
        printf("Host at %s mask %s gateway %s\n", ip_str, nm_str, gw_str);

#ifdef PERF
        perf_init("/tmp/simhost.perf");
#endif                          /* PERF */
#if LWIP_STATS
        stats_init();
#endif                          /* STATS */
        mem_init();
        memp_init();
        pbuf_init();
        sys_init();
#ifdef LWIP_TCPDUMP
        tcpdump_init();
#endif

        printf("System initialized.\n");

        sys_thread_new(main_thread, NULL, DEFAULT_THREAD_PRIO);
        pause();
        return 0;
}
/*-----------------------------------------------------------------------------------*/
_______________________________________________
lwip-users mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to