bsdsocket.c

来自「Keil下移植好的lwip基于c166」· C语言 代码 · 共 608 行 · 第 1/2 页

C
608
字号
/* bsdsocket.c - PaulOS embedded operating system
   Copyright (C) 2002  Paul Sheer

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifdef HAVE_NET

#include "mad.h"
#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 seg_sum (struct tcp_seg *c)
{
    int n = 0;
    while (c) {
	n += c->len;
	c = c->next;
    }
    return n;
}

static int seg_count (struct tcp_seg *c)
{
    int n = 0;
    while (c) {
	n++;
	c = c->next;
    }
    return n;
}

#if 0
void dump_pcb (struct tcp_pcb *pcb)
{
    printf ("next = 0x%x\n", (unsigned int) pcb->next);
    printf ("state = %d\n", (int) pcb->state);
    printf ("callback_arg = 0x%x\n", (unsigned int) pcb->callback_arg);
    printf ("accept = 0x%x\n", (unsigned int) pcb->accept);
    printf ("local_ip = 0x%x\n", (unsigned int) pcb->local_ip.addr);
    printf ("local_port = %d\n", (unsigned int) pcb->local_port);
    printf ("remote_ip = 0x%x\n", (unsigned int) pcb->remote_ip.addr);
    printf ("rcv_nxt = %d\n", (int) pcb->rcv_nxt);
    printf ("rcv_wnd = %d\n", (int) pcb->rcv_wnd);
    printf ("tmr = %d\n", (int) pcb->tmr);
    printf ("rtime = %d\n", (int) pcb->rtime);
    printf ("flags = %d\n", (int) pcb->flags);
    printf ("rttest = %d\n", (int) pcb->rttest);
    printf ("rtseq = %d\n", (int) pcb->rtseq);
    printf ("sa = %d\n", (int) pcb->sa);
    printf ("sv = %d\n", (int) pcb->sv);
    printf ("rto = %d\n", (int) pcb->rto);
    printf ("nrtx = %d\n", (int) pcb->nrtx);
    printf ("lastack = %d\n", (int) pcb->lastack);
    printf ("dupacks = %d\n", (int) pcb->dupacks);
    printf ("cwnd = %d\n", (int) pcb->cwnd);
    printf ("ssthresh = %d\n", (int) pcb->ssthresh);
    printf ("snd_nxt = %d\n", (int) pcb->snd_nxt);
    printf ("snd_max = %d\n", (int) pcb->snd_max);
    printf ("snd_wnd = %d\n", (int) pcb->snd_wnd);
    printf ("snd_wl1 = %d\n", (int) pcb->snd_wl1);
    printf ("snd_wl2 = %d\n", (int) pcb->snd_wl2);
    printf ("snd_lbb = %d\n", (int) pcb->snd_lbb);
    printf ("snd_buf = %d\n", (int) pcb->snd_buf);
    printf ("snd_snd_queuelen = %d\n", (int) pcb->snd_queuelen);
    printf ("sent = 0x%x\n", (unsigned int) pcb->sent);
    printf ("acked = %d\n", (int) pcb->acked);
    printf ("recv = 0x%x\n", (unsigned int) pcb->recv);
    printf ("recv_data = 0x%x, tot_len = %d\n", (unsigned int) pcb->recv_data, pcb->recv_data ? (int) pcb->recv_data->tot_len : 0);
    printf ("connected = 0x%x\n", (unsigned int) pcb->connected);
    printf ("poll = 0x%x\n", (unsigned int) pcb->poll);
    printf ("errf = 0x%x\n", (unsigned int) pcb->errf);
    printf ("polltmr = %d\n", (int) pcb->polltmr);
    printf ("pollinterval = %d\n", (int) pcb->pollinterval);
    printf ("unsent = %d, %d\n", seg_sum (pcb->unsent), seg_count (pcb->unsent));
    printf ("unacked = %d, %d\n", seg_sum (pcb->unacked), seg_count (pcb->unacked));
#if 0
    printf ("ooseg = %d\n", seg_sum (pcb->ooseg), seg_count (pcb->ooseg));
#endif
    printf ("\n");
};
#endif








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 (packet_item, char *data; int len;);
LIST_TYPE_DECLARE (incoming_item, struct socket_info *s;);

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 */
	    int in_packet_offset;
	    int shutdown_how;
	} stream;
    } d;
};

static void incoming_free (incoming_item * p)
{
    if (!p->s)
	return;
    if (p->s->pcb) {
	tcp_arg (p->s->pcb, NULL);
	tcp_sent (p->s->pcb, NULL);
	tcp_recv (p->s->pcb, NULL);
	tcp_err (p->s->pcb, NULL);
	tcp_close (p->s->pcb);
    }
    ldeleteall (p->s->d.stream.packet_list);
    free (p->s);
}

static void packet_free (packet_item * p)
{
    free (p->data);
}

static err_t _socket_sent (void *arg, struct tcp_pcb *pcb, u16_t len)
{
    struct socket_info *info = (struct socket_info *) arg;
    if (!pcb->unacked && !pcb->unsent) {
	tcp_close (pcb);
	tcp_sent (pcb, NULL);
	tcp_abort (pcb);	/* I like closure in a relationship */
	info->pcb = 0;
	return ERR_CLSD;
    }
    return ERR_OK;
}

static int _socket_close (struct tcp_pcb *pcb)
{
    if (pcb) {
	tcp_arg (pcb, NULL);
	tcp_sent (pcb, NULL);
	tcp_recv (pcb, NULL);
	tcp_err (pcb, NULL);
	if (!pcb->unacked && !pcb->unsent) {
	    tcp_close (pcb);
	    tcp_abort (pcb);	/* I like closure in a relationship */
	    return ERR_CLSD;
	} else {
	    tcp_sent (pcb, _socket_sent);
	}
    }
    return ERR_OK;
}

#if 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;
}
#endif

static void _socket_error (void *arg, err_t err)
{
    struct socket_info *info = (struct socket_info *) arg;
    ldeleteall (info->d.stream.packet_list);
printf ("_socket_error\n");
    info->pcb = 0;
}

static void _listener_error (void *arg, err_t err)
{
    struct socket_info *info = (struct socket_info *) arg;
    ldeleteall (info->d.listener.incoming_list);
printf ("_listener_error\n");
    info->pcb = 0;
}

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->pcb);
	info->pcb = 0;
    } else {
	ldeleteall (info->d.stream.packet_list);
	_socket_close (info->pcb);
	info->pcb = 0;
    }
    free (o);
}

static inline int _socket_write_space (struct socket_info *info)
{
#if 0
    if (stats.memp[MEMP_TCP_SEG].used > stats.memp[MEMP_TCP_SEG].avail / 2)
	return 0;
#else
//    if (smsc_packet_count () > 10)	/* FIXME: do we need this? */
//	return 0;
    if (mem_usage_percent (0) > 50)
	return 0;
#endif
    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) */
	if (global_callback ()) {
	    errno = EINTR;
	    return -1;
	}
	if (!info->pcb)		/* socket closed */
	    return 0;
    } while (_socket_write_space (info) <= 0);

//dump_pcb (info->pcb);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?