bsdsocket.c
来自「Keil下移植好的lwip基于c166」· C语言 代码 · 共 608 行 · 第 1/2 页
C
608 行
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) {
err = _socket_close (info->pcb);
printf ("_socket_recv, error\n");
info->pcb = 0;
return err;
}
if (err == ERR_OK && p != NULL) {
char *s;
struct pbuf *q;
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);
s = j->data = (char *) malloc (p->tot_len); /* FIXME: check return value */
j->len = p->tot_len;
for (q = p; q; q = q->next) {
memcpy (s, q->payload, q->len);
s += q->len;
}
pbuf_free (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) */
if (global_callback ()) {
errno = EINTR;
return -1;
}
if (!info->pcb) /* socket closed */
return 0;
if ((j = lhead (info->d.stream.packet_list)))
if (j->len > 0)
break;
}
/* FIXME: quadruple check this algorithm */
for (;;) {
int c;
c = min (len, j->len - info->d.stream.in_packet_offset);
if (!c)
break; /* out of space */
memcpy (s, j->data + 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 == j->len) {
info->d.stream.in_packet_offset = 0;
ldeleteinc (info->d.stream.packet_list, j);
if (!j)
break; /* nothing left to process */
}
}
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->len);
return total;
}
total = lcount (info->d.listener.incoming_list);
/* return a count of the incoming connections */
return total;
}
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 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 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_ABRT;
if (mem_usage_percent (0) > 25)
return ERR_ABRT;
/* add a new connection to our list of pending incoming connections */
lappend (info->d.listener.incoming_list);
j = ltail (info->d.listener.incoming_list);
j->s = (struct socket_info *) malloc (sizeof (struct socket_info));
if (!j->s) {
ldeleteinc (info->d.listener.incoming_list, j);
return ERR_ABRT;
}
memset (j->s, 0, sizeof (struct socket_info));
/* setup list member structure */
linit (j->s->d.stream.packet_list, packet_item, packet_free);
j->s->type = STREAM_MAGIC;
j->s->pcb = pcb;
/* tcp callbacks */
tcp_arg (j->s->pcb, (void *) j->s);
tcp_recv (j->s->pcb, _socket_recv);
tcp_err (j->s->pcb, _socket_error);
return ERR_OK;
}
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 SIOSHUTDOWN:
if (info->type != STREAM_MAGIC) {
errno = ENOTSOCK;
return -1;
}
if (!info->pcb) {
errno = ENOTCONN;
return -1;
}
info->d.stream.shutdown_how |= 1 << *config;
if (info->d.stream.shutdown_how >= (1 << *config)) {
_socket_close (info->pcb);
info->pcb = 0;
}
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 = (struct socket_info *) o;
void *r;
if (info->type != LISTENER_MAGIC) {
errno = ENOTSOCK;
return 0;
}
if (*addrlen != sizeof (struct sockaddr_in)) {
errno = EFAULT;
return 0;
}
j = lhead (info->d.listener.incoming_list);
if (!j) {
errno = EAGAIN;
return 0;
}
while (!j->s->pcb) {
/* loop through sockets that closed before accept() could be called by the upper level application */
ldeleteinc (info->d.listener.incoming_list, j);
if (!j) {
errno = EAGAIN;
return 0;
}
}
r = (void *) j->s;
j->s = 0; /* zero it so the structure doesn't get free'd */
ldeleteinc (info->d.listener.incoming_list, j); /* remove from listener queue */
return r;
}
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,
};
#endif /* HAVE_NET */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?