lwip-users
[Top][All Lists]
Advanced

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

[lwip-users] [lwip] unregister


From: Hieu Thao
Subject: [lwip-users] [lwip] unregister
Date: Wed, 08 Jan 2003 22:20:48 -0000

----- Original Message -----
From: <address@hidden>
To: <address@hidden>
Cc: <address@hidden>
Sent: Monday, February 18, 2002 4:37 PM
Subject: [lwip] lwIP crashing after 17MB of data transfer


>
> Hi Adam and others
>
> I still have a problem with lwip-cvs-20020215 that I had
> with a previous version, lwip-cvs-20020114
>
> I have created a BSD socket layer (way below) for PaulOS.
> I use nc (net cat) to dump many megs through this echo
> server...
>
>
> [[[
>
> #include <stdlib.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <socket.h>
> #include "lwip/lwip/src/include/lwip/stats.h"
>
> #define min(a,b) ((a) < (b) ? (a) : (b))
> #define max(a,b) ((a) > (b) ? (a) : (b))
>
> static int listen_socket (int listen_port)
> {
>     struct sockaddr_in a;
>     int s;
>     if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
> perror ("socket() failed");
> return -1;
>     }
>     memset (&a, 0, sizeof (a));
>     a.sin_port = htons (listen_port);
>     a.sin_family = AF_INET;
>     if (bind (s, (struct sockaddr *) &a, sizeof (a)) < 0) {
> perror ("bind() failed");
> close (s);
> return -1;
>     }
>     printf ("accepting connections on port %d\n", (int) listen_port);
>     listen (s, 10);
>     return s;
> }
>
> int main (int argc, char **argv)
> {
>     int fd, s, r, l = 0;
>     char buf[2048];
>     struct sockaddr_in a;
>     int i = 0;
>
>     s = listen_socket (81);
>     for (;;) {
> l = sizeof (struct sockaddr_in);
> fd = accept (s, (struct sockaddr *) &a, &l);
> for (;;) {
>     char *p;
>     r = read (fd, buf, 1024);
>     if (r <= 0) {
> perror ("read");
> break;
>     }
>     p = buf;
>     while (r > 0) {
> int c;
> c = write (fd, p, min (1024, r));
> if (c <= 0) {
>     perror ("write");
>     goto out;
> }
> p += c;
> r -= c;
>     }
> }
>       out:
> close (fd);
>     }
> }
>
> ]]]
>
>
> but after dumping 17 megs it dies unexpectedly. I turn
> on debug, but with debug on, it works perfectly. It also
> works perfectly if I add a small delay to the main loop.
> It seems to only break when it runs flat out, and then
> always in exactly the same place. After it dies I can
> still ping it though.
>
> I added code to the above to check memory usage but
> memory usage is really very small.
>
> I am using much more memory than the default lwipopts.h
>  - i have raised most of the values by an order of
> magnitude. Note that this is running on an Atmel ARM7TDMI
> with 512kB of SRAM.
>
> any ideas??
>
> -paul
>
> ---------------------------
>
>
> #include "lwip/debug.h"
> #include "lwip/stats.h"
> #include "lwip/tcp.h"
> #include "errno.h"
> #include "file.h"
> #include "list.h"
> #include "sys/ioctl.h"
>
> static int lwip_error_to_errno (int v)
> {
>     const int e[] =
> { 0, ENOMEM, ENOBUFS, ECONNABORTED, ECONNRESET, ESHUTDOWN, ENOTCONN,
EINVAL, EINVAL,
> EHOSTUNREACH,
> EADDRINUSE
>     };
>     return e[-v];
> }
>
> #define min(a,b) ((a) < (b) ? (a) : (b))
> #define max(a,b) ((a) > (b) ? (a) : (b))
>
> LIST_TYPE_DECLARE (incoming_item, struct tcp_pcb * pcb;);
> LIST_TYPE_DECLARE (packet_item, struct pbuf *pbuf;);
>
> static void incoming_free (incoming_item * p)
> {
>     if (p->pcb) {
> tcp_arg (p->pcb, NULL);
> tcp_sent (p->pcb, NULL);
> tcp_recv (p->pcb, NULL);
> tcp_close (p->pcb);
>     }
> }
>
> static void packet_free (packet_item * p)
> {
>     pbuf_free (p->pbuf);
> }
>
> struct socket_info {
> #define LISTENER_MAGIC 0x95de8a3b
> #define STREAM_MAGIC 0x3fd740ab
>     int type;
>     int ref; /* number of times dup'ed */
>     struct tcp_pcb *pcb;
>     union {
> struct {
>     int listener_queue_max_len;
>      LIST_DECLARE (incoming_list, incoming_item); /* queued incoming
connections for
> listening sockets */
> } listener;
> struct {
>     LIST_DECLARE (packet_list, packet_item); /* queued incoming packets
for connected
> sockets */
>     struct pbuf *current;
>     int in_packet_offset;
> } stream;
>     } d;
> };
>
> static void _socket_close (struct socket_info *info)
> {
>     if (info->pcb) {
> tcp_arg (info->pcb, NULL);
> tcp_sent (info->pcb, NULL);
> tcp_recv (info->pcb, NULL);
> tcp_close (info->pcb);
> info->pcb = 0;
>     }
> }
>
>
> static err_t _socket_poll (void *arg, struct tcp_pcb *pcb)
> {
>     if (arg == NULL) {
> tcp_close (pcb);
>     }
> #if 0
>     else {
> send_data (pcb, (struct http_state *) arg);
>     }
> #endif
>
>     return ERR_OK;
> }
>
> static void _socket_error (void *arg, err_t err)
> {
>     struct socket_info *info = (struct socket_info *) arg;
>     ldeleteall (info->d.stream.packet_list);
>     if (info->pcb)
> _socket_close (info);
> }
>
> static void _listener_error (void *arg, err_t err)
> {
>     struct socket_info *info = (struct socket_info *) arg;
>     ldeleteall (info->d.listener.incoming_list);
>     if (info->pcb)
> _socket_close (info);
> }
>
> static void *socket_dup (void *o)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     info->ref++;
>     return info;
> }
>
> static void socket_close (void *o)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     if (info->ref) {
> info->ref--;
> return;
>     }
>     if (info->type == LISTENER_MAGIC) {
> ldeleteall (info->d.listener.incoming_list);
> _socket_close (info);
>     } else {
> ldeleteall (info->d.stream.packet_list);
> _socket_close (info);
>     }
>     free (o);
> }
>
> static inline int _socket_write_space (struct socket_info *info)
> {
>     if (stats.memp[MEMP_TCP_SEG].used > stats.memp[MEMP_TCP_SEG].avail /
2)
> return 0;
>     return tcp_sndbuf (info->pcb);
> }
>
> static int socket_write_space (void *o, int n)
> {
>     struct socket_info *info = (struct socket_info *) o;
>
>     if (info->type != STREAM_MAGIC)
> return -1;
>
>     if (!info->pcb)
> return -1;
>
>     return _socket_write_space (info);
> }
>
> static int socket_write (void *o, unsigned char *s, int len)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     err_t err;
>
>     if (info->type != STREAM_MAGIC) {
> errno = ENOTSOCK;
> return -1;
>     }
>
>     if (!info->pcb) {
> errno = ENOTCONN;
> return -1;
>     }
>
>     do {
> /* explicit (i.e. one extra) */
> global_callback ();
> if (!info->pcb) /* socket closed */
>     return 0;
>     } while (_socket_write_space (info) <= 0);
>
>     len = min (len, tcp_sndbuf (info->pcb));
>
>     err = tcp_write (info->pcb, s, len, 1);
>
>     if (err == ERR_OK) {
> if (!info->pcb->unacked)
>     tcp_output (info->pcb);
> return len;
>     }
>     errno = lwip_error_to_errno (err);
>     return -1;
> }
>
> static int socket_write_queue (void *o)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     struct tcp_seg *unsent;
>     int total = 0;
>     if (info->type != STREAM_MAGIC)
> return -1;
>     if (!info->pcb)
> return -1;
>     for (unsent = info->pcb->unsent; unsent; unsent = unsent->next)
> total += unsent->len;
>     return total;
> }
>
> static int socket_write_nonblock (void *o, unsigned char *s, int len)
> {
>     if (socket_write_space (o, 0))
> return socket_write (o, s, len);
>     errno = EAGAIN;
>     return -1;
> }
>
> err_t _socket_recv (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t
err)
> {
>     struct socket_info *info = (struct socket_info *) arg;
>     if (err == ERR_OK && p == NULL) {
> _socket_close (info);
>     }
>     if (err == ERR_OK && p != NULL) {
> struct packet_item *j;
> /* record the packet in our list for later reading */
> lappend (info->d.stream.packet_list);
> j = ltail (info->d.stream.packet_list);
> j->pbuf = p;
>     }
>     return ERR_OK;
> }
>
> static int socket_read (void *o, unsigned char *s, int len)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     struct packet_item *j;
>     int r = 0;
>
>     if (info->type != STREAM_MAGIC) {
> errno = ENOTSOCK;
> return -1;
>     }
>
>     if (!info->pcb) {
> errno = ENOTCONN;
> return -1;
>     }
>
>     for (;;) {
> /* explicit (i.e. always one extra callback) */
> global_callback ();
> if (!info->pcb) /* socket closed */
>     return 0;
> if ((j = lhead (info->d.stream.packet_list)))
>     if (j->pbuf->tot_len > 0)
> break;
>     }
>
> /* start at the first pbuf in the segment */
>     if (!info->d.stream.current) {
> info->d.stream.current = j->pbuf;
> info->d.stream.in_packet_offset = 0;
>     }
>
> /* FIXME: quadruple check this algorithm */
>     for (;;) {
> int c;
> c = min (len, info->d.stream.current->len -
info->d.stream.in_packet_offset);
> if (!c)
>     break; /* out of space */
> memcpy (s, info->d.stream.current->payload +
info->d.stream.in_packet_offset, c);
> s += c;
> r += c;
> len -= c;
> info->d.stream.in_packet_offset += c;
> if (info->d.stream.in_packet_offset == info->d.stream.current->len) {
>     info->d.stream.current = info->d.stream.current->next;
>     info->d.stream.in_packet_offset = 0;
> }
> if (!info->d.stream.current) {
> /* consumed all pbufs, so delete segment */
>     ldeleteinc (info->d.stream.packet_list, j);
>     if (!j)
> break; /* nothing left to process */
>     info->d.stream.current = j->pbuf;
> }
>     }
>
>     tcp_recved (info->pcb, r);
>
>     tcp_output (info->pcb);
>
>     return r;
> }
>
> static int socket_read_avail (void *o, int n)
> {
>     packet_item *j;
>     int total = 0;
>
>     struct socket_info *info = (struct socket_info *) o;
>
>     if (info->type == STREAM_MAGIC) {
> if (!info->pcb)
>     return -1;
> lsearchforward (info->d.stream.packet_list, j, total += j->pbuf->tot_len);
> return total;
>     }
>
> /* return a count of the incoming connections */
>     return lcount (info->d.listener.incoming_list);
> }
>
> static int socket_read_nonblock (void *o, unsigned char *s, int len)
> {
>     if (socket_read_avail (o, 0))
> return socket_read (o, s, len);
>     errno = EAGAIN;
>     return -1;
> }
>
> static err_t _socket_accept (void *arg, struct tcp_pcb *pcb, err_t err)
> {
>     struct socket_info *info = (struct socket_info *) arg;
>     incoming_item *j;
>
>     if (lcount (info->d.listener.incoming_list) >=
> info->d.listener.listener_queue_max_len)
> return ERR_MEM;
>
>     lappend (info->d.listener.incoming_list);
>     j = ltail (info->d.listener.incoming_list);
>     j->pcb = pcb;
>
>     return ERR_OK;
> }
>
> static void *socket_socket (void *param, int arg1, int arg2)
> {
>     struct socket_info *info;
>
>     info = (struct socket_info *) malloc (sizeof (struct socket_info));
>     if (!info) {
> errno = ENOMEM;
> return 0;
>     }
>     memset (info, 0, sizeof (struct socket_info));
>     info->pcb = tcp_new ();
>     if (!info->pcb) {
> errno = ENOMEM;
> free (info);
> return 0;
>     }
>     info->type = LISTENER_MAGIC;
>     linit (info->d.listener.incoming_list, incoming_item, incoming_free);
>     tcp_err (info->pcb, _listener_error);
>     return (void *) info;
> }
>
> static int socket_ioctl (void *o, int cmd, int *config)
> {
>     struct socket_info *info = (struct socket_info *) o;
>     struct sockaddr_in *s = (struct sockaddr_in *) config;
>     err_t r;
>     switch (cmd) {
>     case SIOBIND:
> if (info->type != LISTENER_MAGIC) {
>     errno = ENOTSOCK;
>     return -1;
> }
> r = tcp_bind (info->pcb, (struct ip_addr *) &s->sin_addr, ntohs
(s->sin_port));
> if (r != ERR_OK) {
>     errno = lwip_error_to_errno (r);
>     return -1;
> }
> return 0;
>     case SIOLISTEN:
> if (info->type != LISTENER_MAGIC) {
>     errno = ENOTSOCK;
>     return -1;
> }
> info->pcb = tcp_listen (info->pcb);
> info->d.listener.listener_queue_max_len = *config;
> tcp_arg (info->pcb, o);
> tcp_accept (info->pcb, _socket_accept);
> return 0;
>     }
>     errno = EINVAL;
>     return -1;
> }
>
> static void *socket_accept (void *o, struct sockaddr *addr, int *addrlen)
> {
>     incoming_item *j;
>     struct socket_info *info, *linfo = (struct socket_info *) o;
>
>     if (linfo->type != LISTENER_MAGIC) {
> errno = ENOTSOCK;
> return 0;
>     }
>     if (*addrlen != sizeof (struct sockaddr_in)) {
> errno = EFAULT;
> return 0;
>     }
>
>     j = lhead (linfo->d.listener.incoming_list);
>     if (!j) {
> errno = EAGAIN;
> return 0;
>     }
>     info = (struct socket_info *) malloc (sizeof (struct socket_info));
>     if (!info) {
> errno = ENOMEM;
> return 0;
>     }
>     memset (info, 0, sizeof (struct socket_info));
>     info->type = STREAM_MAGIC;
>     linit (info->d.stream.packet_list, packet_item, packet_free);
>
>     info->pcb = j->pcb;
>     j->pcb = 0; /* set to zero so it doesn't free */
>
> /* remove from listener queue */
>     ldeleteinc (linfo->d.listener.incoming_list, j);
>
>     tcp_arg (info->pcb, (void *) info);
>     tcp_recv (info->pcb, _socket_recv);
>     tcp_err (info->pcb, _socket_error);
>     tcp_poll (info->pcb, _socket_poll, 4);
>
>     return (void *) info;
> }
>
> struct file file_socket = {
>     socket_socket, /* we use the open() method */
>     socket_dup,
>     socket_close,
>     socket_ioctl,
>     0,
>     socket_write,
>     socket_write,
>     socket_write_space,
>     socket_write_nonblock,
>     0,
>     socket_read,
>     socket_read,
>     socket_read_avail,
>     socket_read_nonblock,
>     socket_write_queue,
>     0,
>     0,
>     socket_accept,
> };
>
>
>
>
>
>
>
> ---------------------------------------------
> This message was sent using World Mail.
> http://www.worldonline.co.za
>
>
> [This message was sent through the lwip discussion list.]

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




reply via email to

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