[Top][All Lists]
[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.]
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lwip-users] [lwip] unregister,
Hieu Thao <=