lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] Re: [lwip] Problems with TCP


From: Rajaraman Krishnan
Subject: [lwip-users] Re: [lwip] Problems with TCP
Date: Thu, 09 Jan 2003 01:34:55 -0000

This is a multi-part message in MIME format.

------=_NextPart_000_0029_01C1B16A.ACFFCEA0
Content-Type: text/plain;
        charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hi Adam,

Thanks for answering my question. That solved the problem. I am now able to
run the TCP server on the LwIP stack and the client on the normal Linux IP
stack over the TAP/TUN interface. However I now have problem when I try it
the otherway around. i.e. I have a TCP client implemented over the LwIP
stack and the server on the Linux IP stack.

When I issue a tcp_connect on the LwIP side, I get these messages "Send ARP
after query" a few times and then my HandleConnect() call gets called with
an error. It seems like the Linux stack is not responding to the ARPs. All I
was doing to initialise this interface was call the tapif_init on the LwIP
side. Is anything more required?

Anyway I got around this problem by explicitly pinging this LwIP node from
another window in the Linux machine. That I figured would eliminate the need
for ARP. It did fix that problem. But then I get the following message when
I try to write to this connection,

Assertion "tcp_enqueue: valid queue length" failed at line 178 in
/home/rajaram/utils/lwip-0.5.0/src/core/tcp_output.c
Aborted


Thanks,

Rajaram




----- Original Message -----
From: "Adam Dunkels" <address@hidden>
To: <address@hidden>
Sent: Friday, February 08, 2002 6:56 PM
Subject: Re: [lwip] Problems with TCP


> Hi!
>
> On Thursday 07 February 2002 08.55, you wrote:
> > Can someone throw some light on what is going on? BTW I did think about
> > using the TCP code from shell.c but that doesnt use the Raw API and the
API
> > it uses (i.e. netconn_*) is not documented anywhere.
>
> The problem is because your HandleNewConnection() function blocks on
> sys_sem_wait(). Since this function is executed in the TCP/IP thread, it
must
> not block, since this will block the entire TCP/IP stack. The raw API
> requires a slight mindshift from the threaded programming model to the
> callback/event based model.
>
> In your case, you shouldn't wait for the semaphore. Instead, you should
put
> the code that comes after sys_sem_wait() in your ReadSocket() function.
>
> The sequential API (netconn_*) is documented in the paper found in the
> "Documentation" section on the lwIP homepage. Since programs using the
> sequential API runs in a different thread from the TCP/IP stack, there are
no
> problems with blocking there.
>
> /adam
> --
> Adam Dunkels <address@hidden>
> http://www.sics.se/~adam
> [This message was sent through the lwip discussion list.]
>

------=_NextPart_000_0029_01C1B16A.ACFFCEA0
Content-Type: application/octet-stream;
        name="server.cc"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="server.cc"

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>

#define MAX_STRING 100

int sockfd;

// Send a buffer to the Wrapper.
int WriteSocket(char *msg)
{
    ulong bufLen =3D strlen(msg)+1;
    ulong tmpLen, writeLen =3D 0;

    while (writeLen < bufLen)
    {
        if ((tmpLen =3D write(sockfd, msg+writeLen, bufLen)) <=3D 0)
        {
            printf("write error\n");
            return 1;
        }
        writeLen +=3D tmpLen;
    }

    return 0;
}

// Read the message from socket
// Read the message from socket
int ReadSocket(char *msg)
{
    ulong tmpLen, readLen =3D 0;

    while (1)
    {
        if ((tmpLen =3D read(sockfd, msg+readLen, MAX_STRING)) <=3D 0)
        {
            printf("read error\n");
            return 1;
        }
        printf("Read Something.\n");
        readLen +=3D tmpLen;
        if (msg[readLen-1] =3D=3D '\0') return 0;
    }
}

/*-----------------------------------------------------------------------=
----
|  Setup socket
|------------------------------------------------------------------------=
--*/
void SetupServerSocket(char* name, int port)=20
{
    /* start the socket server */
    struct sockaddr_in addr, peer;
    socklen_t sockAddrLen, peerAddrLen;

    /* create what looks like an ordinary UDP socket */
    if ((sockfd=3Dsocket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("socket");
          exit(1);
    }
   =20
    /* set up destination address */
    memset(&addr,0,sizeof(addr));
    addr.sin_family=3DAF_INET;
    addr.sin_addr.s_addr=3Dhtonl(INADDR_ANY);
    addr.sin_port=3Dhtons(port);

    /* bind to receive address */
    if (bind(sockfd,(struct sockaddr *) &addr,sizeof(addr)) < 0)
    {
        perror("bind failed: ");
        exit(1);
    }
   =20
    /* listen to the socket */
    printf("Bind OK. Listening for connect.\n");
    listen(sockfd, 5);

    peerAddrLen =3D sizeof(peer);
    /* accept the socket, and create a peer socket to listen */
    if ((sockfd =3D accept(sockfd, (struct sockaddr *)&peer, =
&peerAddrLen)) < 0 )
    {
        perror("accept");
        exit(1);
    }
    printf("Connected.\n");
}

main(int argc, char **argv)
{
    ulong port;
    char msg[MAX_STRING];

    if (argc !=3D 2)
    {
        printf("Usage: %s <portNo>\n",  argv[0]);
        exit(1);
    }

    if (sscanf(argv[1], "%d", &port) !=3D 1)
    {
        printf("Usage: %s <portNo>\n",  argv[0]);
        exit(1);
    }

    printf("Binding the socket and listening on port %d.\n", port);

    SetupServerSocket(argv[2], port);
    printf("Receiving message from client.\n");
    ReadSocket(msg);
    printf("Message Received: %s. \nSending Reply: Hi2U2.\n", msg);
    WriteSocket("Hi2U2Hi2U2");
    printf("Message Sent.\n");
}

------=_NextPart_000_0029_01C1B16A.ACFFCEA0
Content-Type: application/octet-stream;
        name="lwip_client.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="lwip_client.c"

#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/tunif.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 <stdio.h>

#define MAX_STRING 100

typedef struct
{
    char msg[MAX_STRING];
    int len;
} ReceiveDetails;

struct ip_addr host, gw;
int port;

// Read the message from socket
err_t ReadSocket(void * arg, struct tcp_pcb *dsock, struct pbuf *p, =
err_t err)
{
    struct pbuf* np;
    ReceiveDetails *recv =3D (ReceiveDetails *)arg;

    printf("Data to be read in connection.\n");

    if (err !=3D 0)
    {
        printf("Error in HandleNewConn.\n");
        exit(1);
    }

    if (p =3D=3D NULL)
    {
        printf("Server closed connection.\n");

        /* Close the Dsock. */
        tcp_close(dsock);

        exit(1);
    }

    np =3D p;
    while (np !=3D NULL)
    {
        printf("Processing packet at %p.\n", np);
        printf("Processing packet of length: %d of total %d at %d.\n",
               np->len, np->tot_len, recv->len);
        memcpy(recv->msg+recv->len, np->payload, np->len);
        recv->len +=3D np->len;
        np =3D np->next;
    }

    printf("Received all bufs. Total len =3D %d.\n", recv->len);
    tcp_recved(dsock, p->tot_len);

    /* Check if a full string has been received. */
    if (recv->msg[recv->len-1] =3D=3D '\0')
    {
        printf("Message Received: %s. \nSending Reply: Hi2U2.\n", recv->msg);
        tcp_close(dsock);
        exit(0);
    }

    return 0;
}

err_t HandleConnect(void *arg, struct tcp_pcb *dsock, err_t err)
{
    ReceiveDetails *recv;

    recv =3D (ReceiveDetails *) malloc(sizeof(ReceiveDetails));

    if (err !=3D 0)
    {
        printf("Error in HandleNewConn.\n");
        exit(1);
    }

    printf("Connected.\n");

    printf("Sending message to Server: Hello.\n");
    tcp_write(dsock, "Hello", 6, 1);
    printf("Message Sent.\n");

    recv->len =3D 0;
    tcp_arg(dsock, recv);

    tcp_recv(dsock, ReadSocket);
    return 0;
}


/*-----------------------------------------------------------------------=
----
|  Setup socket
|------------------------------------------------------------------------=
--*/
void TcpCommunicate(int port)=20
{
    struct tcp_pcb *sock;

    /* create what looks like an ordinary TCP socket */
    if ((sock =3D tcp_new()) =3D=3D NULL)
    {
        printf("Problems with tcp_new.\n");
        exit(1);
    }

    printf("Connecting to %d.%d.%d.%d on port %d.\n",=20
           (u8_t)(ntohl(gw.addr) >> 24) & 0xff, \
           (u8_t)(ntohl(gw.addr) >> 16) & 0xff, \
           (u8_t)(ntohl(gw.addr) >> 8) & 0xff, \
           (u8_t)ntohl(gw.addr) & 0xff, port);

    if (tcp_connect(sock, &gw, port, HandleConnect))
    {
        printf("Problems with tcp_connect.\n");
        exit(1);
    }
}

void lwip_if_init()
{
    struct ip_addr lbaddr, netmask, lbgw;

   =20
    IP4_ADDR(&netmask, 255,255,255,0);
 =20
    netif_set_default(netif_add(&host, &netmask, &gw, tapif_init,
                                tcpip_input));

    IP4_ADDR(&lbgw, 127,0,0,1);
    IP4_ADDR(&lbaddr, 127,0,0,1);
    IP4_ADDR(&netmask, 255,0,0,0);
 =20
    netif_add(&lbaddr, &netmask, &lbgw, loopif_init, tcpip_input);
}

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

void lwip_init()
{
    sys_init();
    mem_init();
    memp_init();
    pbuf_init();
}

void main_thread(void *arg)
{
    char tmp[MAX_STRING];
    sys_sem_t sem;

    lwip_if_init();

    sem =3D sys_sem_new(0);
    tcpip_init(tcpip_init_done, &sem);
    sys_sem_wait(sem);
    sys_sem_free(sem);
    printf("TCP/IP initialized.\n"
           "Hit <RETURN> to proceed.");

    fflush(stdin);
    fgets(tmp, MAX_STRING, stdin);

    TcpCommunicate(port);

    /* Block for ever. */
    sem =3D sys_sem_new(0);
    sys_sem_wait(sem);
}


int parse_addr(char *caddr, struct ip_addr *ipaddr1, struct ip_addr =
*ipaddr2)
{
    int a, b, c, d;

    if (sscanf(caddr, "%d.%d.%d.%d", &a, &b, &c, &d) !=3D 4)
        return 0;

    if ((a < 0) || (a > 255) || (b < 0) || (b > 255) || (c < 0) || (c > =
255) ||
        (d < 0) || (d > 254))
        return 0;

    IP4_ADDR(ipaddr1, a, b, c, d);
    IP4_ADDR(ipaddr2, a, b, c, (d+1));
    return 1;
}


int main(int argc, char **argv)
{
    if (argc !=3D 3)
    {
        printf("Usage: %s <Sim IP Address> <portNo>\n",  argv[0]);
        exit(1);
    }

    if (!parse_addr(argv[1], &host, &gw))
    {
        printf("Usage: %s <Sim IP Address> <portNo>\n",  argv[0]);
        printf("\t<Sim IP Address> should be of the form A.B.C.D.\n");

        exit(1);
    }

    lwip_init();

    printf("System initialized.\n");

    if (sscanf(argv[2], "%d", &port) !=3D 1)
    {
        printf("Usage: %s <Sim IP Address> <portNo>\n",  argv[0]);
        printf("\t<Sim IP Address> should be of the form A.B.C.D.\n");

        exit(1);
    }

    sys_thread_new((void *)(main_thread), NULL);
    pause();
    return 0;
}

------=_NextPart_000_0029_01C1B16A.ACFFCEA0--

[This message was sent through the lwip discussion list.]




reply via email to

[Prev in Thread] Current Thread [Next in Thread]