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 + -
显示快捷键?