lwip-users
[Top][All Lists]
Advanced

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

[lwip-users] [lwip] Code Review requested


From: David Haas
Subject: [lwip-users] [lwip] Code Review requested
Date: Thu, 09 Jan 2003 00:10:15 -0000

This is a multi-part message in MIME format.

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: multipart/alternative;
        boundary="----=_NextPart_001_000E_01C2A52C.35B69F20"


------=_NextPart_001_000E_01C2A52C.35B69F20
Content-Type: text/plain;
        charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable

Hi,

I have finished coding for a select() function in the sockets interface. =
I have made sure it compiles, but I have not tested it yet. I am =
attaching the changed files with all changes marked by /* *****Added by =
DJH */ or /* *****Changed by DJH */=20
I did not mark the changes in cc.h since that file is specific to my =
architecture. I added the fd_set definitions to it, but I'm not sure if =
this is the right spot.

I would request that some of you take a look at these changes and do =
some code review to make sure I have solved the problem without breaking =
anything obvious and I have not screwed anything up for anyone else. I =
will submit the changes as a patch later when I have tested it.=20

This implementation does not support exceptset.

It does support timeouts.




David Haas
NBS Card Technology
70 Eisenhower Drive,
Paramus, NJ 07652
Voice: 201-845-7373 x183
Fax: 201-845-3337
email: address@hidden

------=_NextPart_001_000E_01C2A52C.35B69F20
Content-Type: text/html;
        charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Dwindows-1252">
<META content=3D"MSHTML 6.00.2800.1126" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT size=3D2>Hi,</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>I have finished coding for a select() function in =
the sockets=20
interface. I have made sure it compiles, but I have not tested it yet. I =
am=20
attaching the changed files with all changes marked by /* *****Added by =
DJH */=20
or /* *****Changed by DJH */ </FONT></DIV>
<DIV><FONT size=3D2>I did not mark the changes in cc.h since that file =
is specific=20
to my architecture. I added the fd_set definitions to it, but I'm not =
sure if=20
this is the right spot.</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>I would request that some of you take a look at =
these changes=20
and do some code review to make sure I have solved the problem without =
breaking=20
anything obvious and I have not screwed anything up for anyone else. I =
will=20
submit the changes as a patch later when I have tested it. </FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>This implementation does not support =
exceptset.</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>It does support timeouts.</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>David Haas<BR>NBS Card Technology<BR>70 Eisenhower=20
Drive,<BR>Paramus, NJ 07652<BR>Voice: 201-845-7373 x183<BR>Fax:=20
201-845-3337<BR>email: <A=20
href=3D"mailto:address@hidden";>address@hidden</A><BR></FONT></DIV><=
/BODY></HTML>

------=_NextPart_001_000E_01C2A52C.35B69F20--

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="api_lib.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="api_lib.c"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */

/* This is the part of the API that is linked with
   the application */

#include "lwip/debug.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"

#include "lwip/debug.h"

/*-----------------------------------------------------------------------=
------------*/
struct
netbuf *netbuf_new(void)
{
  struct netbuf *buf;

  buf =3D memp_mallocp(MEMP_NETBUF);
  if(buf !=3D NULL) {
    buf->p =3D NULL;
    buf->ptr =3D NULL;
    return buf;
  } else {
    return NULL;
  }
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_delete(struct netbuf *buf)
{
  if(buf !=3D NULL) {
    if(buf->p !=3D NULL) {
      pbuf_free(buf->p);
      buf->p =3D buf->ptr =3D NULL;
    }
    memp_freep(MEMP_NETBUF, buf);
  }
}
/*-----------------------------------------------------------------------=
------------*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
  /* Deallocate any previously allocated memory. */
  if(buf->p !=3D NULL) {
    pbuf_free(buf->p);
  }
  buf->p =3D pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
  if(buf->p =3D=3D NULL) {
     return NULL;
  }
  buf->ptr =3D buf->p;
  return buf->p->payload;
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_free(struct netbuf *buf)
{
  if(buf->p !=3D NULL) {
    pbuf_free(buf->p);
  }
  buf->p =3D buf->ptr =3D NULL;
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
{
  if(buf->p !=3D NULL) {
    pbuf_free(buf->p);
  }
  buf->p =3D pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_ROM);
  buf->p->payload =3D dataptr;
  buf->p->len =3D buf->p->tot_len =3D size;
  buf->ptr =3D buf->p;
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
  pbuf_chain(head->p, tail->p);
  head->ptr =3D head->p;
  memp_freep(MEMP_NETBUF, tail);
}
/*-----------------------------------------------------------------------=
------------*/
u16_t
netbuf_len(struct netbuf *buf)
{
  return buf->p->tot_len;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
  if(buf->ptr =3D=3D NULL) {
    return ERR_BUF;
  }
  *dataptr =3D buf->ptr->payload;
  *len =3D buf->ptr->len;
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
s8_t
netbuf_next(struct netbuf *buf)
{
  if(buf->ptr->next =3D=3D NULL) {
    return -1;
  }
  buf->ptr =3D buf->ptr->next;
  if(buf->ptr->next =3D=3D NULL) {
    return 1;
  }
  return 0;
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_first(struct netbuf *buf)
{
  buf->ptr =3D buf->p;
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t =
offset)
{
  struct pbuf *p;
  u16_t i, left;

  left =3D 0;

  if(buf =3D=3D NULL) {
    return;
  }
 =20
  /* This implementation is bad. It should use bcopy
     instead. */
  for(p =3D buf->p; left < len && p !=3D NULL; p =3D p->next) {
    if(offset !=3D 0 && offset >=3D p->len) {
      offset -=3D p->len;
    } else {   =20
      for(i =3D offset; i < p->len; ++i) {
        ((char *)dataptr)[left] =3D ((char *)p->payload)[i];
        if(++left >=3D len) {
          return;
        }
      }
      offset =3D 0;
    }
  }
}
/*-----------------------------------------------------------------------=
------------*/
void
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
{
  netbuf_copy_partial(buf, dataptr, len, 0);
}
/*-----------------------------------------------------------------------=
------------*/
struct ip_addr *
netbuf_fromaddr(struct netbuf *buf)
{
  return buf->fromaddr;
}
/*-----------------------------------------------------------------------=
------------*/
u16_t
netbuf_fromport(struct netbuf *buf)
{
  return buf->fromport;
}
/*-----------------------------------------------------------------------=
------------*/
struct
netconn *netconn_new(enum netconn_type t)
{
  struct netconn *conn;

  conn =3D memp_mallocp(MEMP_NETCONN);
  if(conn =3D=3D NULL) {
    return NULL;
  }
  conn->type =3D t;
  conn->pcb.tcp =3D NULL;

  if((conn->mbox =3D sys_mbox_new()) =3D=3D SYS_MBOX_NULL) {
    memp_freep(MEMP_NETCONN, conn);
    return NULL;
  }
  conn->recvmbox =3D SYS_MBOX_NULL;
  conn->acceptmbox =3D SYS_MBOX_NULL;
  conn->sem =3D SYS_SEM_NULL;
  conn->state =3D NETCONN_NONE;
/* *****Added by DJH */
  conn->socket =3D 0;
  conn->callback =3D 0;
/* *****             */
  return conn;
}
/* *****Added by DJH */
/*-----------------------------------------------------------------------=
------------*/
struct
netconn *netconn_new_with_callback(enum netconn_type t,
                                   void (*callback)(struct netconn *, =
enum netconn_evt))
{
    struct netconn *conn;
   =20
    /* get a netconn and then initialize callback pointer and socket */
    conn =3D netconn_new(t);
    if (conn)
        conn->callback =3D callback;
    return conn;
}
/* *****             */

/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_delete(struct netconn *conn)
{
  struct api_msg *msg;
  void *mem;
 =20
  if(conn =3D=3D NULL) {
    return ERR_OK;
  }
 =20
  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return ERR_MEM;
  }
 =20
  msg->type =3D API_MSG_DELCONN;
  msg->msg.conn =3D conn;
  api_msg_post(msg); =20
  sys_mbox_fetch(conn->mbox, NULL);
  memp_freep(MEMP_API_MSG, msg);

  /* Drain the recvmbox. */
  if(conn->recvmbox !=3D SYS_MBOX_NULL) {
    while(sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) !=3D 0) {
      if(conn->type =3D=3D NETCONN_TCP) {
        pbuf_free((struct pbuf *)mem);
      } else {
        netbuf_delete((struct netbuf *)mem);
      }
    }
    sys_mbox_free(conn->recvmbox);
    conn->recvmbox =3D SYS_MBOX_NULL;
  }
=20

  /* Drain the acceptmbox. */
  if(conn->acceptmbox !=3D SYS_MBOX_NULL) {
    while(sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) !=3D 0) {
      netconn_delete((struct netconn *)mem);
    }
   =20
    sys_mbox_free(conn->acceptmbox);
    conn->acceptmbox =3D SYS_MBOX_NULL;
  }

  sys_mbox_free(conn->mbox);
  conn->mbox =3D SYS_MBOX_NULL;
  if(conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_free(conn->sem);
  }
  /*  conn->sem =3D SYS_SEM_NULL;*/
  memp_free(MEMP_NETCONN, conn);
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
enum netconn_type
netconn_type(struct netconn *conn)
{
  return conn->type;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_peer(struct netconn *conn, struct ip_addr **addr,
             u16_t *port)
{
  switch(conn->type) {
  case NETCONN_UDPLITE:
  case NETCONN_UDPNOCHKSUM:
  case NETCONN_UDP:
    *addr =3D &(conn->pcb.udp->remote_ip);
    *port =3D conn->pcb.udp->remote_port;
    break;
  case NETCONN_TCP:
    *addr =3D &(conn->pcb.tcp->remote_ip);
    *port =3D conn->pcb.tcp->remote_port;
    break;
  }
  return (conn->err =3D ERR_OK);
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_addr(struct netconn *conn, struct ip_addr **addr,
             u16_t *port)
{
  switch(conn->type) {
  case NETCONN_UDPLITE:
  case NETCONN_UDPNOCHKSUM:
  case NETCONN_UDP:
    *addr =3D &(conn->pcb.udp->local_ip);
    *port =3D conn->pcb.udp->local_port;
    break;
  case NETCONN_TCP:
    *addr =3D &(conn->pcb.tcp->local_ip);
    *port =3D conn->pcb.tcp->local_port;
    break;
  }
  return (conn->err =3D ERR_OK);
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr,
            u16_t port)
{
  struct api_msg *msg;

  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }

  if(conn->type !=3D NETCONN_TCP &&
     conn->recvmbox =3D=3D SYS_MBOX_NULL) {
    if((conn->recvmbox =3D sys_mbox_new()) =3D=3D SYS_MBOX_NULL) {
      return ERR_MEM;
    }
  }
 =20
  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return (conn->err =3D ERR_MEM);
  }
  msg->type =3D API_MSG_BIND;
  msg->msg.conn =3D conn;
  msg->msg.msg.bc.ipaddr =3D addr;
  msg->msg.msg.bc.port =3D port;
  api_msg_post(msg);
  sys_mbox_fetch(conn->mbox, NULL);
  memp_freep(MEMP_API_MSG, msg);
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr,
                   u16_t port)
{
  struct api_msg *msg;
 =20
  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }


  if(conn->recvmbox =3D=3D SYS_MBOX_NULL) {
    if((conn->recvmbox =3D sys_mbox_new()) =3D=3D SYS_MBOX_NULL) {
      return ERR_MEM;
    }
  }
 =20
  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return ERR_MEM;
  }
  msg->type =3D API_MSG_CONNECT;
  msg->msg.conn =3D conn; =20
  msg->msg.msg.bc.ipaddr =3D addr;
  msg->msg.msg.bc.port =3D port;
  api_msg_post(msg);
  sys_mbox_fetch(conn->mbox, NULL);
  memp_freep(MEMP_API_MSG, msg);
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_listen(struct netconn *conn)
{
  struct api_msg *msg;

  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }

  if(conn->acceptmbox =3D=3D SYS_MBOX_NULL) {
    conn->acceptmbox =3D sys_mbox_new();
    if(conn->acceptmbox =3D=3D SYS_MBOX_NULL) {
      return ERR_MEM;
    }
  }
 =20
  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return (conn->err =3D ERR_MEM);
  }
  msg->type =3D API_MSG_LISTEN;
  msg->msg.conn =3D conn;
  api_msg_post(msg);
  sys_mbox_fetch(conn->mbox, NULL);
  memp_freep(MEMP_API_MSG, msg);
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
struct netconn *
netconn_accept(struct netconn *conn)
{
  struct netconn *newconn;
 =20
  if(conn =3D=3D NULL) {
    return NULL;
  }
 =20
  sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
/* *****Added by DJH */
  /* Register event with callback */
  if (conn->callback)
      (*conn->callback)(conn, NETCONN_EVT_RCVMINUS);
/* *****             */
 =20
  return newconn;
}
/*-----------------------------------------------------------------------=
------------*/
struct netbuf *
netconn_recv(struct netconn *conn)
{
  struct api_msg *msg;
  struct netbuf *buf;
  struct pbuf *p;
   =20
  if(conn =3D=3D NULL) {
    return NULL;
  }
 =20
  if(conn->recvmbox =3D=3D SYS_MBOX_NULL) {
    conn->err =3D ERR_CONN;
    return NULL;
  }

  if(conn->err !=3D ERR_OK) {
    return NULL;
  }

  if(conn->type =3D=3D NETCONN_TCP) {
    if(conn->pcb.tcp->state =3D=3D LISTEN) {
      conn->err =3D ERR_CONN;
      return NULL;
    }


    buf =3D memp_mallocp(MEMP_NETBUF);

    if(buf =3D=3D NULL) {
      conn->err =3D ERR_MEM;
      return NULL;
    }
   =20
    sys_mbox_fetch(conn->recvmbox, (void **)&p);
/* *****Added by DJH */
    /* Register event with callback */
    if (conn->callback)
        (*conn->callback)(conn, NETCONN_EVT_RCVMINUS);
/* *****             */

    /* If we are closed, we indicate that we no longer wish to recieve
       data by setting conn->recvmbox to SYS_MBOX_NULL. */
    if(p =3D=3D NULL) {
      memp_freep(MEMP_NETBUF, buf);
      sys_mbox_free(conn->recvmbox);
      conn->recvmbox =3D SYS_MBOX_NULL;
      return NULL;
    }

    buf->p =3D p;
    buf->ptr =3D p;
    buf->fromport =3D 0;
    buf->fromaddr =3D NULL;

    /* Let the stack know that we have taken the data. */
    if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
      conn->err =3D ERR_MEM;
      return buf;
    }
    msg->type =3D API_MSG_RECV;
    msg->msg.conn =3D conn;
    if(buf !=3D NULL) {
      msg->msg.msg.len =3D buf->p->tot_len;
    } else {
      msg->msg.msg.len =3D 1;
    }
    api_msg_post(msg);

    sys_mbox_fetch(conn->mbox, NULL);
    memp_freep(MEMP_API_MSG, msg);
  } else {
    sys_mbox_fetch(conn->recvmbox, (void **)&buf);
/* *****Added by DJH */
    /* Register event with callback */
    if (conn->callback)
        (*conn->callback)(conn, NETCONN_EVT_RCVMINUS);
/* *****             */
  }

 =20

   =20
  DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", buf, =
conn->err));


  return buf;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
  struct api_msg *msg;

  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }

  if(conn->err !=3D ERR_OK) {
    return conn->err;
  }

  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return (conn->err =3D ERR_MEM);
  }

  DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", =
buf->p->tot_len));
  msg->type =3D API_MSG_SEND;
  msg->msg.conn =3D conn;
  msg->msg.msg.p =3D buf->p;
  api_msg_post(msg);

  sys_mbox_fetch(conn->mbox, NULL);
  memp_freep(MEMP_API_MSG, msg);
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t =
copy)
{
  struct api_msg *msg;
  u16_t len;
 =20
  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }

  if(conn->err !=3D ERR_OK) {
    return conn->err;
  }
 =20
  if(conn->sem =3D=3D SYS_SEM_NULL) {
    conn->sem =3D sys_sem_new(0);
    if(conn->sem =3D=3D SYS_SEM_NULL) {
      return ERR_MEM;
    }
  }

  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return (conn->err =3D ERR_MEM);
  }
  msg->type =3D API_MSG_WRITE;
  msg->msg.conn =3D conn;
       =20

  conn->state =3D NETCONN_WRITE;
  while(conn->err =3D=3D ERR_OK && size > 0) {
    msg->msg.msg.w.dataptr =3D dataptr;
    msg->msg.msg.w.copy =3D copy;
   =20
    if(conn->type =3D=3D NETCONN_TCP) {
      if(tcp_sndbuf(conn->pcb.tcp) =3D=3D 0) {
        sys_sem_wait(conn->sem);
        if(conn->err !=3D ERR_OK) {
          goto ret;
        }
      }
      if(size > tcp_sndbuf(conn->pcb.tcp)) {
        /* We cannot send more than one send buffer's worth of data at a
           time. */
        len =3D tcp_sndbuf(conn->pcb.tcp);
      } else {
        len =3D size;
      }
    } else {
      len =3D size;
    }
   =20
    DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", =
len, copy));
    msg->msg.msg.w.len =3D len;
    api_msg_post(msg);
    sys_mbox_fetch(conn->mbox, NULL);   =20
    if(conn->err =3D=3D ERR_OK) {
      dataptr =3D (void *)((char *)dataptr + len);
      size -=3D len;
    } else if(conn->err =3D=3D ERR_MEM) {
      conn->err =3D ERR_OK;
      sys_sem_wait(conn->sem);
    } else {
      goto ret;
    }
  }
 ret:
  memp_freep(MEMP_API_MSG, msg);
  conn->state =3D NETCONN_NONE;
  if(conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_free(conn->sem);
    conn->sem =3D SYS_SEM_NULL;
  }
/* *****Added by DJH */
  if (conn->callback)
      if (conn->type =3D=3D NETCONN_TCP && conn->err =3D=3D ERR_OK)
      {
          if (tcp_sndbuf(conn->pcb.tcp) <=3D TCP_SNDLOWAT)
              (*conn->callback)(conn, NETCONN_EVT_SENDMINUS);
      }
/* *****             */
 =20
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_close(struct netconn *conn)
{
  struct api_msg *msg;

  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }
  if((msg =3D memp_mallocp(MEMP_API_MSG)) =3D=3D NULL) {
    return (conn->err =3D ERR_MEM);
  }

  conn->state =3D NETCONN_CLOSE;
 again:
  msg->type =3D API_MSG_CLOSE;
  msg->msg.conn =3D conn;
  api_msg_post(msg);
  sys_mbox_fetch(conn->mbox, NULL);
  if(conn->err =3D=3D ERR_MEM &&
     conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_wait(conn->sem);
    goto again;
  }
  conn->state =3D NETCONN_NONE;
  memp_freep(MEMP_API_MSG, msg);
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/
err_t
netconn_err(struct netconn *conn)
{
  return conn->err;
}
/*-----------------------------------------------------------------------=
------------*/

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="api_msg.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="api_msg.c"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */

#include "lwip/debug.h"
#include "lwip/arch.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"

/*-----------------------------------------------------------------------=
------------*/
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  struct netconn *conn;

  conn =3D arg;

  if(conn =3D=3D NULL) {
    pbuf_free(p);
    return ERR_VAL;
  }

  if(conn->recvmbox !=3D SYS_MBOX_NULL) {
    conn->err =3D err;
/* *****Added by DJH */
    /* Register event with callback */
    if (conn->callback)
        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS);
/* *****             */
    sys_mbox_post(conn->recvmbox, p);
  } =20
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
#if LWIP_UDP
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
         struct ip_addr *addr, u16_t port)
{
  struct netbuf *buf;
  struct netconn *conn;

  conn =3D arg;
 =20
  if(conn =3D=3D NULL) {
    pbuf_free(p);
    return;
  }

  if(conn->recvmbox !=3D SYS_MBOX_NULL) {
    buf =3D memp_mallocp(MEMP_NETBUF);
    if(buf =3D=3D NULL) {
      pbuf_free(p);
      return;
    } else {
      buf->p =3D p;
      buf->ptr =3D p;
      buf->fromaddr =3D addr;
      buf->fromport =3D port;
    }

/* *****Added by DJH */
    /* Register event with callback */
    if (conn->callback)
        (*conn->callback)(conn, NETCONN_EVT_RCVPLUS);
/* *****             */
    sys_mbox_post(conn->recvmbox, buf);
  }
}
#endif /* LWIP_UDP */
/*-----------------------------------------------------------------------=
------------*/
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
  struct netconn *conn;

  conn =3D arg;
  if(conn !=3D NULL &&
     (conn->state =3D=3D NETCONN_WRITE || conn->state =3D=3D =
NETCONN_CLOSE) &&
     conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_signal(conn->sem);
  }
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct netconn *conn;

  conn =3D arg;
  if(conn !=3D NULL && conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_signal(conn->sem);
  }

/* *****Added by DJH */
  if (conn && conn->callback)
      if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)
          (*conn->callback)(conn, NETCONN_EVT_SENDPLUS);
/* *****             */
 =20
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
static void
err_tcp(void *arg, err_t err)
{
  struct netconn *conn;

  conn =3D arg;

  conn->pcb.tcp =3D NULL;

 =20
  conn->err =3D err;
  if(conn->recvmbox !=3D SYS_MBOX_NULL) {
/* *****Added by DJH */
    /* Register event with callback */
    if (conn->callback)
      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS);
/* *****             */
    sys_mbox_post(conn->recvmbox, NULL);
  }
  if(conn->mbox !=3D SYS_MBOX_NULL) {
    sys_mbox_post(conn->mbox, NULL);
  }
  if(conn->acceptmbox !=3D SYS_MBOX_NULL) {
/* *****Added by DJH */
     /* Register event with callback */
    if (conn->callback)
      (*conn->callback)(conn, NETCONN_EVT_RCVPLUS);
/* *****             */
    sys_mbox_post(conn->acceptmbox, NULL);
  }
  if(conn->sem !=3D SYS_SEM_NULL) {
    sys_sem_signal(conn->sem);
  }
}
/*-----------------------------------------------------------------------=
------------*/
static void
setup_tcp(struct netconn *conn)
{
  struct tcp_pcb *pcb;
 =20
  pcb =3D conn->pcb.tcp;
  tcp_arg(pcb, conn);
  tcp_recv(pcb, recv_tcp);
  tcp_sent(pcb, sent_tcp);
  tcp_poll(pcb, poll_tcp, 4);
  tcp_err(pcb, err_tcp);
}
/*-----------------------------------------------------------------------=
------------*/
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
/* *****Changed by DJH */
  sys_mbox_t mbox;
/* *****             */
  struct netconn *newconn;
/* *****Added by DJH */
  struct netconn *conn;
/* *****             */
 =20
#if API_MSG_DEBUG
#if TCP_DEBUG
  tcp_debug_print_state(newpcb->state);
#endif /* TCP_DEBUG */
#endif /* API_MSG_DEBUG */
/* *****Changed by DJH */
  conn =3D (struct netconn *)arg;
  mbox =3D conn->acceptmbox;
/* *****             */
  newconn =3D memp_mallocp(MEMP_NETCONN);
  if(newconn =3D=3D NULL) {
    return ERR_MEM;
  }
  newconn->type =3D NETCONN_TCP;
  newconn->pcb.tcp =3D newpcb;
  setup_tcp(newconn);
  newconn->recvmbox =3D sys_mbox_new();
  if(newconn->recvmbox =3D=3D SYS_MBOX_NULL) {
    memp_free(MEMP_NETCONN, newconn);
    return ERR_MEM;
  }
  newconn->mbox =3D sys_mbox_new();
  if(newconn->mbox =3D=3D SYS_MBOX_NULL) {
    sys_mbox_free(newconn->recvmbox);
    memp_free(MEMP_NETCONN, newconn);
    return ERR_MEM;
  }
  newconn->sem =3D sys_sem_new(0);
  if(newconn->sem =3D=3D SYS_SEM_NULL) {
    sys_mbox_free(newconn->recvmbox);
    sys_mbox_free(newconn->mbox);
    memp_free(MEMP_NETCONN, newconn);
    return ERR_MEM;
  }
  newconn->acceptmbox =3D SYS_MBOX_NULL;
  newconn->err =3D err;
/* *****Added by DJH */
  /* Register event with callback */
  if (conn->callback)
    (*conn->callback)(conn, NETCONN_EVT_RCVPLUS);
/* *****             */
/* *****Changed by DJH */
  sys_mbox_post(mbox, newconn);
/* *****             */
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_newconn(struct api_msg_msg *msg)
{
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_delconn(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:
      msg->conn->pcb.udp->recv_arg =3D NULL;
      udp_remove(msg->conn->pcb.udp);
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      if(msg->conn->pcb.tcp->state =3D=3D LISTEN) {
        tcp_accept(msg->conn->pcb.tcp, NULL);=09
        tcp_close(msg->conn->pcb.tcp);
      } else {
        tcp_arg(msg->conn->pcb.tcp, NULL);
        tcp_sent(msg->conn->pcb.tcp, NULL);
        tcp_recv(msg->conn->pcb.tcp, NULL);=09
        tcp_poll(msg->conn->pcb.tcp, NULL, 0);
        tcp_err(msg->conn->pcb.tcp, NULL);
        if(tcp_close(msg->conn->pcb.tcp) !=3D ERR_OK) {
          tcp_abort(msg->conn->pcb.tcp);
        }
      }
    break;
    }
  }
  if(msg->conn->mbox !=3D SYS_MBOX_NULL) {
    sys_mbox_post(msg->conn->mbox, NULL);
  }
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_bind(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp =3D=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      msg->conn->pcb.udp =3D udp_new();
      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
    case NETCONN_UDPNOCHKSUM:
      msg->conn->pcb.udp =3D udp_new();
      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
    case NETCONN_UDP:
      msg->conn->pcb.udp =3D udp_new();
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      msg->conn->pcb.tcp =3D tcp_new();
      setup_tcp(msg->conn);
      break;
    }
  }
  switch(msg->conn->type) {
#if LWIP_UDP
  case NETCONN_UDPLITE:
    /* FALLTHROUGH */
  case NETCONN_UDPNOCHKSUM:
    /* FALLTHROUGH */
  case NETCONN_UDP:
    udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
    break;
#endif /* LWIP_UDP */
  case NETCONN_TCP:
    msg->conn->err =3D tcp_bind(msg->conn->pcb.tcp,
                              msg->msg.bc.ipaddr, msg->msg.bc.port);
    break;
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
  struct netconn *conn;

  conn =3D arg;

  if(conn =3D=3D NULL) {
    return ERR_VAL;
  }
 =20
  conn->err =3D err;

  if(conn->type =3D=3D NETCONN_TCP && err =3D=3D ERR_OK) {
    setup_tcp(conn);
  }   =20
 =20
  sys_mbox_post(conn->mbox, NULL);
  return ERR_OK;
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_connect(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp =3D=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      msg->conn->pcb.udp =3D udp_new();
      if(msg->conn->pcb.udp =3D=3D NULL) {
        msg->conn->err =3D ERR_MEM;
        sys_mbox_post(msg->conn->mbox, NULL);
        return;
      }
      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
    case NETCONN_UDPNOCHKSUM:
      msg->conn->pcb.udp =3D udp_new();
      if(msg->conn->pcb.udp =3D=3D NULL) {
        msg->conn->err =3D ERR_MEM;
        sys_mbox_post(msg->conn->mbox, NULL);
        return;
      }
      udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
    case NETCONN_UDP:
      msg->conn->pcb.udp =3D udp_new();
      if(msg->conn->pcb.udp =3D=3D NULL) {
        msg->conn->err =3D ERR_MEM;
        sys_mbox_post(msg->conn->mbox, NULL);
        return;
      }
      udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      msg->conn->pcb.tcp =3D tcp_new();     =20
      if(msg->conn->pcb.tcp =3D=3D NULL) {
        msg->conn->err =3D ERR_MEM;
        sys_mbox_post(msg->conn->mbox, NULL);
        return;
      }
      break;
    }
  }
  switch(msg->conn->type) {
#if LWIP_UDP
  case NETCONN_UDPLITE:
    /* FALLTHROUGH */
  case NETCONN_UDPNOCHKSUM:
    /* FALLTHROUGH */
  case NETCONN_UDP:
    udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, =
msg->msg.bc.port);
    sys_mbox_post(msg->conn->mbox, NULL);
    break;
#endif=20
  case NETCONN_TCP:
    /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
    setup_tcp(msg->conn);
    tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, =
msg->msg.bc.port,
                do_connected);
    /*tcp_output(msg->conn->pcb.tcp);*/
    break;
  }
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_listen(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:
      DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for =
UDP.\n"));
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      msg->conn->pcb.tcp =3D tcp_listen(msg->conn->pcb.tcp);
      if(msg->conn->pcb.tcp =3D=3D NULL) {
        msg->conn->err =3D ERR_MEM;
      } else {
        if(msg->conn->acceptmbox =3D=3D SYS_MBOX_NULL) {
          msg->conn->acceptmbox =3D sys_mbox_new();
          if(msg->conn->acceptmbox =3D=3D SYS_MBOX_NULL) {
            msg->conn->err =3D ERR_MEM;
            break;
          }
        }
        tcp_arg(msg->conn->pcb.tcp, (void *)&(msg->conn->acceptmbox));
        tcp_accept(msg->conn->pcb.tcp, accept_function);
      }
      break;
    }
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_accept(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:   =20
      DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for =
UDP.\n"));
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      break;
    }
  }
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_send(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:
      udp_send(msg->conn->pcb.udp, msg->msg.p);
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      break;
    }
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_recv(struct api_msg_msg *msg)
{
  if(msg->conn->pcb.tcp !=3D NULL) {
    if(msg->conn->type =3D=3D NETCONN_TCP) {
      tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
    }
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_write(struct api_msg_msg *msg)
{
  err_t err;
  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP=20
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:
      msg->conn->err =3D ERR_VAL;
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:     =20
      err =3D tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
                      msg->msg.w.len, msg->msg.w.copy);
      /* This is the Nagle algorithm: inhibit the sending of new TCP
         segments when new outgoing data arrives from the user if any
         previously transmitted data on the connection remains
         unacknowledged. */
      if(err =3D=3D ERR_OK && msg->conn->pcb.tcp->unacked =3D=3D NULL) {
        tcp_output(msg->conn->pcb.tcp);
      }
      msg->conn->err =3D err;
      break;
    }
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
static void
do_close(struct api_msg_msg *msg)
{
  err_t err;

  err =3D ERR_OK;

  if(msg->conn->pcb.tcp !=3D NULL) {
    switch(msg->conn->type) {
#if LWIP_UDP
    case NETCONN_UDPLITE:
      /* FALLTHROUGH */
    case NETCONN_UDPNOCHKSUM:
      /* FALLTHROUGH */
    case NETCONN_UDP:
      break;
#endif /* LWIP_UDP */
    case NETCONN_TCP:
      if(msg->conn->pcb.tcp->state =3D=3D LISTEN) {
        err =3D tcp_close(msg->conn->pcb.tcp);
      }
      msg->conn->err =3D err;     =20
      break;
    }
  }
  sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] =3D {
  do_newconn,
  do_delconn,
  do_bind,
  do_connect,
  do_listen,
  do_accept,
  do_send,
  do_recv,
  do_write,
  do_close
  };
void
api_msg_input(struct api_msg *msg)
{ =20
  decode[msg->type](&(msg->msg));
}
/*-----------------------------------------------------------------------=
------------*/
void
api_msg_post(struct api_msg *msg)
{
  tcpip_apimsg(msg);
}
/*-----------------------------------------------------------------------=
------------*/



------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="sockets.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="sockets.c"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */

#include "lwip/debug.h"
#include "lwip/api.h"

#include "lwip/sockets.h"

#define NUM_SOCKETS 10

struct lwip_socket {
  struct netconn *conn;
  struct netbuf *lastdata;
  u16_t lastoffset;
/* *****Added by DJH */
  u16_t rcvevent;
  u16_t sendevent;
/* *****             */
};

/* *****Added by DJH */
struct lwip_select_cb=20
{
    struct lwip_select_cb *next;
    fd_set *readset;
    fd_set *writeset;
    fd_set *exceptset;
    int sem_signalled;
    sys_sem_t sem;
};
/* *****             */

static struct lwip_socket sockets[NUM_SOCKETS];
/* *****Added by DJH */
static struct lwip_select_cb *select_cb_list =3D 0;

static sys_sem_t socksem =3D 0;

static void
event_callback(struct netconn *conn, enum netconn_evt evt);
/* *****             */

/*-----------------------------------------------------------------------=
------------*/
static struct lwip_socket *
get_socket(int s)
{
  struct lwip_socket *sock;
 =20
  if(s > NUM_SOCKETS) {
    /* errno =3D EBADF; */
    return NULL;
  }
 =20
  sock =3D &sockets[s];

  if(sock->conn =3D=3D NULL) {
    /* errno =3D EBADF; */
    return NULL;
  }
  return sock;
}
/*-----------------------------------------------------------------------=
------------*/
static int
alloc_socket(struct netconn *newconn)
{
  int i;
/* *****Added by DJH */

  if (!socksem)
      socksem =3D sys_sem_new(1);

  /* Protect socket array */
  sys_sem_wait(socksem);
/* *****             */
 =20
  /* allocate a new socket identifier */
  for(i =3D 0; i < NUM_SOCKETS; ++i) {
    if(sockets[i].conn =3D=3D NULL) {
      sockets[i].conn =3D newconn;
      sockets[i].lastdata =3D NULL;
      sockets[i].lastoffset =3D 0;
/* *****Added by DJH */
      sockets[i].rcvevent =3D 0;
      sockets[i].sendevent =3D 1; /* TCP send buf is empty */
      sys_sem_signal(socksem);
/* *****             */
      return i;
    }
  }
/* *****Added by DJH */
  sys_sem_signal(socksem);
/* *****             */
  return -1;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_accept(int s, struct sockaddr *addr, int *addrlen)
{
  struct lwip_socket *sock;
  struct netconn *newconn;
  struct ip_addr *naddr;
  u16_t port;
  int newsock;

  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
 =20
  newconn =3D netconn_accept(sock->conn);
   =20
  /* get the IP address and port of the remote host */
  netconn_peer(newconn, &naddr, &port);
 =20
  ((struct sockaddr_in *)addr)->sin_addr.s_addr =3D naddr->addr;
  ((struct sockaddr_in *)addr)->sin_port =3D port;

  newsock =3D alloc_socket(newconn);
  if(newsock =3D=3D -1) { =20
    netconn_delete(newconn);
    /* errno =3D ENOBUFS; */
  }
  return newsock;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_bind(int s, struct sockaddr *name, int namelen)
{
  struct lwip_socket *sock;
  struct ip_addr remote_addr;
  u16_t remote_port;
  err_t err;
 =20
  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
 =20
  remote_addr.addr =3D ((struct sockaddr_in *)name)->sin_addr.s_addr;
  remote_port =3D ((struct sockaddr_in *)name)->sin_port;
 =20
  err =3D netconn_bind(sock->conn, &remote_addr, ntohs(remote_port));

  if(err !=3D ERR_OK) {
    /* errno =3D ... */
    return -1;
  }

  return 0;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_close(int s)
{
  struct lwip_socket *sock;
 =20
  DEBUGF(SOCKETS_DEBUG, ("close: socket %d\n", s));
  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
 =20
 =20
  netconn_delete(sock->conn);
  if(sock->lastdata !=3D NULL) {
    netbuf_delete(sock->lastdata);
  }
  sock->lastdata =3D NULL;
  sock->lastoffset =3D 0;
  sock->conn =3D NULL;
  return 0;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_connect(int s, struct sockaddr *name, int namelen)
{
  struct lwip_socket *sock;
  struct ip_addr remote_addr;
  u16_t remote_port;
  err_t err;

  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
 =20
  remote_addr.addr =3D ((struct sockaddr_in *)name)->sin_addr.s_addr;
  remote_port =3D ((struct sockaddr_in *)name)->sin_port;
 =20
  err =3D netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));

  if(err !=3D ERR_OK) {
    /* errno =3D ... */
    return -1;
  }

  return 0;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_listen(int s, int backlog)
{
  struct lwip_socket *sock;   =20
  err_t err;
 =20
  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
=20
  err =3D netconn_listen(sock->conn);

  if(err !=3D ERR_OK) {
    /* errno =3D ... */
    return -1;
  }

  return 0;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
              struct sockaddr *from, int *fromlen)
{
  struct lwip_socket *sock;
  struct netbuf *buf;
  u16_t buflen, copylen;
  struct ip_addr *addr;
  u16_t port;

 =20
  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }

  /* Check if there is data left from the last recv operation. */
  if(sock->lastdata !=3D NULL) {   =20
    buf =3D sock->lastdata;
  } else {
    /* No data was left from the previous operation, so we try to get
       some from the network. */
    buf =3D netconn_recv(sock->conn);
   =20
    if(buf =3D=3D NULL) {
      /* We should really do some error checking here. */
      return 0;
    }
  }
 =20
  buflen =3D netbuf_len(buf);

  buflen -=3D sock->lastoffset;
 =20
  if(len > buflen) {
    copylen =3D buflen;
  } else {
    copylen =3D len;
  }
 =20
  /* copy the contents of the received buffer into
     the supplied memory pointer mem */
  netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);

  /* If this is a TCP socket, check if there is data left in the
     buffer. If so, it should be saved in the sock structure for next
     time around. */
  if(netconn_type(sock->conn) =3D=3D NETCONN_TCP && buflen - copylen > =
0) {
    sock->lastdata =3D buf;
    sock->lastoffset +=3D copylen;
  } else {
    sock->lastdata =3D NULL;
    sock->lastoffset =3D 0;
    netbuf_delete(buf);
  }

  /* Check to see from where the data was. */
  if(from !=3D NULL && fromlen !=3D NULL) {
    addr =3D netbuf_fromaddr(buf);
    port =3D netbuf_fromport(buf); =20
    ((struct sockaddr_in *)from)->sin_addr.s_addr =3D addr->addr;
    ((struct sockaddr_in *)from)->sin_port =3D port;
    *fromlen =3D sizeof(struct sockaddr_in);
  }
 =20
  return copylen;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_read(int s, void *mem, int len)
{
  return lwip_recv(s, mem, len, 0);
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_recv(int s, void *mem, int len, unsigned int flags)
{
  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_send(int s, void *data, int size, unsigned int flags)
{
  struct lwip_socket *sock;
  struct netbuf *buf;
  err_t err;

  DEBUGF(SOCKETS_DEBUG, ("send: socket %d, size %d\n", s, size));

  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  } =20
 =20
  switch(netconn_type(sock->conn)) {
  case NETCONN_UDP:
    /* create a buffer */
    buf =3D netbuf_new();

    if(buf =3D=3D NULL) {
      /* errno =3D ENOBUFS; */
      return -1;
    }
   =20
    /* make the buffer point to the data that should
       be sent */
    netbuf_ref(buf, data, size);

    /* send the data */
    err =3D netconn_send(sock->conn, buf);

    /* deallocated the buffer */
    netbuf_delete(buf);
    break;
  case NETCONN_TCP:
    err =3D netconn_write(sock->conn, data, size, NETCONN_COPY);
    break;
  default:
    err =3D ERR_ARG;
    break;
  }
  if(err !=3D ERR_OK) {
    /* errno =3D ... */
    return -1;   =20
  }
   =20
  return size;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_sendto(int s, void *data, int size, unsigned int flags,
       struct sockaddr *to, int tolen)
{
  struct lwip_socket *sock;
  struct ip_addr remote_addr, *addr;
  u16_t remote_port, port;
  int ret;

  sock =3D get_socket(s);
  if(sock =3D=3D NULL) {
    return -1;
  }
 =20
  /* get the peer if currently connected */
  netconn_peer(sock->conn, &addr, &port);
 =20
  remote_addr.addr =3D ((struct sockaddr_in *)to)->sin_addr.s_addr;
  remote_port =3D ((struct sockaddr_in *)to)->sin_port;
  netconn_connect(sock->conn, &remote_addr, remote_port);
 =20
  ret =3D lwip_send(s, data, size, flags);

  /* reset the remote address and port number
     of the connection */
  netconn_connect(sock->conn, addr, port);
  return ret;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_socket(int domain, int type, int protocol)
{
  struct netconn *conn;
  int i;

  /* create a netconn */
  switch(type) {
  case SOCK_DGRAM:
/* *****Changed by DJH */
    conn =3D netconn_new_with_callback(NETCONN_UDP, event_callback);
/* *****             */
    break;
  case SOCK_STREAM:
/* *****Changed by DJH */
    conn =3D netconn_new_with_callback(NETCONN_TCP, event_callback);
/* *****             */
    break;
  default:
    /* errno =3D ... */
    return -1;
  }

  if(conn =3D=3D NULL) {
    DEBUGF(SOCKETS_DEBUG, ("socket: could not create netconn.\n"));
    /* errno =3D ENOBUFS; */
    return -1;
  }

  i =3D alloc_socket(conn);

  if(i =3D=3D -1) {
    /* errno =3D ENOBUFS; */
    netconn_delete(conn);
  }
/* *****Added by DJH */
  conn->socket =3D i;
/* *****             */
  return i;
}
/*-----------------------------------------------------------------------=
------------*/
int
lwip_write(int s, void *data, int size)
{
   return lwip_send(s, data, size, 0);
}
/* *****Added by DJH */

/*-----------------------------------------------------------------------=
------------*/
static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set =
*exceptset)
{
    int i, nready =3D 0;
    fd_set lreadset, lwriteset, lexceptset;
    struct lwip_socket *p_sock;

    FD_ZERO(&lreadset);
    FD_ZERO(&lwriteset);
    FD_ZERO(&lexceptset);
   =20
    /* Go through each socket in each list to count number of sockets =
which
       currently match */
    for(i =3D 0; i < maxfdp1; i++)
    {
        if(FD_ISSET(i, readset))
        {
            /* See if netconn of this socket is ready for read */
            p_sock =3D get_socket(i);
            if (p_sock && p_sock->rcvevent)
            {
                FD_SET(i, &lreadset);
                nready++;
            }
        }
        if(FD_ISSET(i, writeset))
        {
            /* See if netconn of this socket is ready for write */
            p_sock =3D get_socket(i);
            if (p_sock && p_sock->sendevent)
            {
                FD_SET(i, &lwriteset);
                nready++;
            }
        }
    }
    *readset =3D lreadset;
    *writeset =3D lwriteset;
    FD_ZERO(exceptset);

    return nready;
}


/*-----------------------------------------------------------------------=
------------*/
int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set =
*exceptset,
               const struct timeval *timeout)
{
    int i;
    int nready;
    fd_set lreadset, lwriteset, lexceptset;
    u16_t msectimeout;
    struct lwip_select_cb select_cb;
    struct lwip_select_cb *p_selcb;

    select_cb.next =3D 0;
    select_cb.readset =3D readset;
    select_cb.writeset =3D writeset;
    select_cb.exceptset =3D exceptset;
    select_cb.sem_signalled =3D 0;
   =20
    /* Protect ourselves searching through the list */
    if (!socksem)
        socksem =3D sys_sem_new(1);
    sys_sem_wait(socksem);
   =20
    lreadset =3D *readset;
    lwriteset =3D *writeset;
    lexceptset =3D *exceptset;
    /* Go through each socket in each list to count number of sockets =
which
       currently match */
    nready =3D lwip_selscan(maxfdp1, &lreadset, &lwriteset, =
&lexceptset);
   =20
    /* If we don't have any current events, then suspend if we are =
supposed to */
    if (!nready)
    {
        if (timeout && timeout->tv_sec =3D=3D 0 && timeout->tv_usec)
        {
            sys_sem_signal(socksem);
            FD_ZERO(readset);
            FD_ZERO(writeset);
            FD_ZERO(exceptset);
            return 0;
        }
       =20
        /* add our semaphore to list */
        /* We don't actually need any dynamic memory. Our entry on the
         * list is only valid while we are in this function, so it's ok
         * to use local variables */

        select_cb.sem =3D sys_sem_new(0);
        /* Note that we are still protected */
        /* Put this select_cb on top of list */
        select_cb.next =3D select_cb_list;
        select_cb_list =3D &select_cb;

        /* Now we can safely unprotect */
        sys_sem_signal(socksem);

        /* Now just wait to be woken */
        if (timeout =3D=3D 0)
            /* Wait forever */
            msectimeout =3D 0;
        else
            msectimeout =3D (u16_t) ((timeout->tv_sec * 1000) + =
(timeout->tv_usec /1000));

        i =3D sys_sem_wait_timeout(select_cb.sem, msectimeout);

        /* Take us off the list */
        sys_sem_wait(socksem);
        for (p_selcb =3D select_cb_list; p_selcb; p_selcb =3D =
p_selcb->next)
            if (p_selcb->next && (p_selcb->next =3D=3D &select_cb))
                p_selcb->next =3D select_cb.next;
        sys_sem_signal(socksem);
       =20
        sys_sem_free(select_cb.sem);
        if (i =3D=3D 0)             /* Timeout */
        {
            FD_ZERO(readset);
            FD_ZERO(writeset);
            FD_ZERO(exceptset);
            return 0;
        }
        /* See what's set */
        nready =3D lwip_selscan(maxfdp1, &lreadset, &lwriteset, =
&lexceptset);
    }
    else
        sys_sem_signal(socksem);
   =20
   =20
    *readset =3D lreadset;
    *writeset =3D lwriteset;
    *exceptset =3D lexceptset;
    return nready;
}

/*-----------------------------------------------------------------------=
------------*/
static void
event_callback(struct netconn *conn, enum netconn_evt evt)
{
    int s;
    struct lwip_socket *sock;
    struct lwip_select_cb *scb;
   =20
    /* Get socket */
    if (conn)
    {
        s =3D conn->socket;
        sock =3D get_socket(s);
        if (!sock)
            return;
    }
    else
        return;
   =20
    /* Set event as required */
    switch (evt)
    {
      case NETCONN_EVT_RCVPLUS:
        sock->rcvevent++;
        break;
      case NETCONN_EVT_RCVMINUS:
        sock->rcvevent--;
        break;
      case NETCONN_EVT_SENDPLUS:
        sock->sendevent =3D 1;
        break;
      case NETCONN_EVT_SENDMINUS:
        sock->sendevent =3D 0;
        break;
    }

    /* Now decide if anyone is waiting for this socket */
    /* NOTE: This code is written this way to protect the select link =
list
       but to avoid a deadlock situation by releasing socksem before
       signalling for the select. This means we need to go through the =
list
       multiple times ONLY IF a select was actually waiting. We go =
through
       the list the number of waiting select calls + 1. This list is
       expected to be small. */
    while (1)
    {
        sys_sem_wait(socksem);
        for (scb =3D select_cb_list; scb; scb =3D scb->next)
        {
            if (scb->sem_signalled =3D=3D 0)
            {
                /* Test this select call for our socket */
                if (FD_ISSET(s, scb->readset))
                    if (sock->rcvevent)
                        break;
                if (FD_ISSET(s, scb->writeset))
                    if (sock->sendevent)
                        break;
            }
        }
        sys_sem_signal(socksem);
        if (scb)
        {
            scb->sem_signalled =3D 1;
            sys_sem_signal(scb->sem);
        }
        else
            break;
    }
   =20
}

/* *****             */
/*-----------------------------------------------------------------------=
------------*/

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="sys.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="sys.c"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */

#include "lwip/debug.h"

#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"

#ifndef NO_SYS

/* *****Added by DJH */
struct sswt_cb
{
    int timeflag;
    sys_sem_t *psem;
};
/* *****             */


/*-----------------------------------------------------------------------=
------------*/
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
  u16_t time;
  struct sys_timeouts *timeouts;
  struct sys_timeout *tmptimeout;
  sys_timeout_handler h;
  void *arg;

   =20
 again:
  timeouts =3D sys_arch_timeouts();
   =20
  if(timeouts->next =3D=3D NULL) {
    sys_arch_mbox_fetch(mbox, msg, 0);
  } else {
    if(timeouts->next->time > 0) {
      time =3D sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
    } else {
      time =3D 0;
    }

    if(time =3D=3D 0) {
      /* If time =3D=3D 0, a timeout occured before a message could be
         fetched. We should now call the timeout handler and
         deallocate the memory allocated for the timeout. */
      tmptimeout =3D timeouts->next;
      timeouts->next =3D tmptimeout->next;
      h =3D tmptimeout->h;
      arg =3D tmptimeout->arg;
      memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
      h(arg);
     =20
      /* We try again to fetch a message from the mbox. */
      goto again;
    } else {
      /* If time > 0, a message was received before the timeout
         occured. The time variable is set to the number of
         microseconds we waited for the message. */
      if(time <=3D timeouts->next->time) {
        timeouts->next->time -=3D time;
      } else {
        timeouts->next->time =3D 0;
      }
    }
   =20
  }
}
/*-----------------------------------------------------------------------=
------------*/
void
sys_sem_wait(sys_sem_t sem)
{
  u16_t time;
  struct sys_timeouts *timeouts;
  struct sys_timeout *tmptimeout;
  sys_timeout_handler h;
  void *arg;
 =20
  /*  while(sys_arch_sem_wait(sem, 1000) =3D=3D 0);
      return;*/

 again:
 =20
  timeouts =3D sys_arch_timeouts();
 =20
  if(timeouts->next =3D=3D NULL) {
    sys_arch_sem_wait(sem, 0);
  } else {
    if(timeouts->next->time > 0) {
      time =3D sys_arch_sem_wait(sem, timeouts->next->time);
    } else {
      time =3D 0;
    }

    if(time =3D=3D 0) {
      /* If time =3D=3D 0, a timeout occured before a message could be
         fetched. We should now call the timeout handler and
         deallocate the memory allocated for the timeout. */
      tmptimeout =3D timeouts->next;
      timeouts->next =3D tmptimeout->next;
      h =3D tmptimeout->h;
      arg =3D tmptimeout->arg;
      memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
      h(arg);
           =20
     =20
      /* We try again to fetch a message from the mbox. */
      goto again;
    } else {
      /* If time > 0, a message was received before the timeout
         occured. The time variable is set to the number of
         microseconds we waited for the message. */
      if(time <=3D timeouts->next->time) {
        timeouts->next->time -=3D time;
      } else {
        timeouts->next->time =3D 0;
      }
    }
   =20
  }
}
/*-----------------------------------------------------------------------=
------------*/
void
sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg)
{
  struct sys_timeouts *timeouts;
  struct sys_timeout *timeout, *t;

  timeout =3D memp_malloc(MEMP_SYS_TIMEOUT);
  if(timeout =3D=3D NULL) {
    return;
  }
  timeout->next =3D NULL;
  timeout->h =3D h;
  timeout->arg =3D arg;
  timeout->time =3D msecs;
 =20
  timeouts =3D sys_arch_timeouts();
 =20
  if(timeouts->next =3D=3D NULL) {
    timeouts->next =3D timeout;
    return;
  } =20
 =20
  if(timeouts->next->time > msecs) {
    timeouts->next->time -=3D msecs;
    timeout->next =3D timeouts->next;
    timeouts->next =3D timeout;
  } else {
    for(t =3D timeouts->next; t !=3D NULL; t =3D t->next) {
      timeout->time -=3D t->time;
      if(t->next =3D=3D NULL ||
         t->next->time > timeout->time) {
        if(t->next !=3D NULL) {
          t->next->time -=3D timeout->time;
        }
        timeout->next =3D t->next;
        t->next =3D timeout;
        break;
      }
    }
  }
 =20
}
/*-----------------------------------------------------------------------=
------------*/
/* *****Added by DJH */
static void
sswt_handler(void *arg)
{
    struct sswt_cb *sswt_cb =3D (struct sswt_cb *) arg;
   =20
    /* Timeout. Set flag to TRUE and signal semephore */
    sswt_cb->timeflag =3D TRUE;
    sys_sem_signal(*(sswt_cb->psem));
}

/* Wait for a semaphore with timeout (specified in ms) */
/* timeout =3D 0: wait forever */
/* Returns 0 on timeout. 1 otherwise */
/*-----------------------------------------------------------------------=
------------*/
int
sys_sem_wait_timeout(sys_sem_t sem, u16_t timeout)
{
    struct sswt_cb sswt_cb;

    sswt_cb.psem =3D &sem;
    sswt_cb.timeflag =3D FALSE;
   =20
    /* If timeout is zero, then just wait forever */
    if (timeout > 0)
        /* Create a timer and pass it the address of our flag */
        sys_timeout(timeout, sswt_handler, &sswt_cb);
    sys_sem_wait(sem);
    /* Was it a timeout? */
    if (sswt_cb.timeflag)
        return 0;
    else
        return 1;
}

/*-----------------------------------------------------------------------=
------------*/
/* *****             */

#endif /* NO_SYS */

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="sys.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="sys.h"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */
#ifndef __LWIP_SYS_H__
#define __LWIP_SYS_H__

#include "arch/cc.h"

#include "lwip/opt.h"

#if NO_SYS

/* For a totally minimal and standalone system, we provide null
   definitions of the sys_ functions. */
typedef u8_t sys_sem_t;
typedef u8_t sys_mbox_t;
struct sys_timeout {u8_t dummy;};

#define sys_init()
#define sys_timeout(m,h,a)
#define sys_sem_new(c) c
#define sys_sem_signal(s)
#define sys_sem_wait(s)
#define sys_sem_free(s)
#define sys_mbox_new() 0
#define sys_mbox_fetch(m,d)
#define sys_mbox_post(m,d)
#define sys_mbox_free(m)

#define sys_thread_new(t,a)

#else /* NO_SYS */

#include "arch/sys_arch.h"

typedef void (* sys_timeout_handler)(void *arg);

struct sys_timeout {
  struct sys_timeout *next;
  u16_t time;
  sys_timeout_handler h;
  void *arg;
};

struct sys_timeouts {
  struct sys_timeout *next;
};

/* sys_init() must be called before anthing else. */
void sys_init(void);

/*
 * sys_timeout():
 *
 * Schedule a timeout a specified amount of milliseconds in the
 * future. When the timeout occurs, the specified timeout handler will
 * be called. The handler will be passed the "arg" argument when
 * called.
 *
 */
void sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg);
struct sys_timeouts *sys_arch_timeouts(void);

/* Semaphore functions. */
sys_sem_t sys_sem_new(u8_t count);
void sys_sem_signal(sys_sem_t sem);
u16_t sys_arch_sem_wait(sys_sem_t sem, u16_t timeout);
void sys_sem_free(sys_sem_t sem);
void sys_sem_wait(sys_sem_t sem);
/* *****Added by DJH */
int
sys_sem_wait_timeout(sys_sem_t sem, u16_t timeout);
/* *****             */

/* Mailbox functions. */
sys_mbox_t sys_mbox_new(void);
void sys_mbox_post(sys_mbox_t mbox, void *msg);
u16_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u16_t timeout);
void sys_mbox_free(sys_mbox_t mbox);
void sys_mbox_fetch(sys_mbox_t mbox, void **msg);

/* Thread functions. */
void sys_thread_new(void (* thread)(void *arg), void *arg);

/* The following functions are used only in Unix code, and
   can be omitted when porting the stack. */
/* Returns the current time in microseconds. */
unsigned long sys_now(void);

#endif /* NO_SYS */

#endif /* __LWIP_SYS_H__ */

------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="sockets.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="sockets.h"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */


#ifndef __LWIP_SOCKETS_H__
#define __LWIP_SOCKETS_H__

struct in_addr {
  u32_t s_addr;
};


struct sockaddr_in {
  u8_t sin_len;
  u8_t sin_family;
  u16_t sin_port;
  struct in_addr sin_addr;
  char sin_zero[8];
};

struct sockaddr {
  u8_t sa_len;
  u8_t sa_family;
  char sa_data[14];
};

#define SOCK_STREAM     1
#define SOCK_DGRAM      2

#define AF_INET         2
#define PF_INET         AF_INET

#define IPPROTO_TCP     6
#define IPPROTO_UDP     17

#define INADDR_ANY      0
#define INADDR_BROADCAST 0xffffffff

int lwip_accept(int s, struct sockaddr *addr, int *addrlen);
int lwip_bind(int s, struct sockaddr *name, int namelen);
int lwip_close(int s);
int lwip_connect(int s, struct sockaddr *name, int namelen);
int lwip_listen(int s, int backlog);
int lwip_recv(int s, void *mem, int len, unsigned int flags);
int lwip_read(int s, void *mem, int len);
int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
                  struct sockaddr *from, int *fromlen);
int lwip_send(int s, void *dataptr, int size, unsigned int flags);
int lwip_sendto(int s, void *dataptr, int size, unsigned int flags,
                struct sockaddr *to, int tolen);
int lwip_socket(int domain, int type, int protocol);
int lwip_write(int s, void *dataptr, int size);
/* *****Added by DJH */
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set =
*exceptset,
                const struct timeval *timeout);
/* *****             */

#ifdef LWIP_COMPAT_SOCKETS
#define accept(a,b,c)         lwip_accept(a,b,c)
#define bind(a,b,c)           lwip_bind(a,b,c)
#define close(s)              lwip_close(s)
#define connect(a,b,c)        lwip_connect(a,b,c)
#define listen(a,b)           lwip_listen(a,b)
#define recv(a,b,c,d)         lwip_recv(a,b,c,d)
#define read(a,b,c)           lwip_read(a,b,c)
#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
#define send(a,b,c,d)         lwip_send(a,b,c,d)
#define sendto(a,b,c,d,e,f)   lwip_sendto(a,b,c,d,e,f)
#define socket(a,b,c)         lwip_socket(a,b,c)
#define write(a,b,c)          lwip_write(a,b,c)
/* *****Added by DJH */
#define select(a,b,c,d,e)     lwip_select(a,b,c,d,e)
/* *****             */
#endif /* LWIP_NO_COMPAT_SOCKETS */

#endif /* __LWIP_SOCKETS_H__ */


------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="api.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="api.h"

/*
 * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
 * All rights reserved.=20
 *=20
 * Redistribution and use in source and binary forms, with or without =
modification,=20
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright =
notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright =
notice,
 *    this list of conditions and the following disclaimer in the =
documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote =
products
 *    derived from this software without specific prior written =
permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED=20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF=20
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO EVENT=20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, =
SPECIAL,=20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, =
PROCUREMENT=20
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER =
IN=20
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR =
OTHERWISE) ARISING=20
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY=20
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 */
#ifndef __LWIP_API_H__
#define __LWIP_API_H__

#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"

#include "lwip/ip.h"

#include "lwip/udp.h"
#include "lwip/tcp.h"

#include "lwip/err.h"

#define NETCONN_NOCOPY 0x00
#define NETCONN_COPY   0x01

enum netconn_type {
  NETCONN_TCP,
  NETCONN_UDP,
  NETCONN_UDPLITE,
  NETCONN_UDPNOCHKSUM
};

enum netconn_state {
  NETCONN_NONE,
  NETCONN_WRITE,
  NETCONN_ACCEPT,
  NETCONN_RECV,
  NETCONN_CONNECT,
  NETCONN_CLOSE
};

/* *****Added by DJH */
enum netconn_evt {
  NETCONN_EVT_RCVPLUS,
  NETCONN_EVT_RCVMINUS,
  NETCONN_EVT_SENDPLUS,
  NETCONN_EVT_SENDMINUS
};
/* *****             */

struct netbuf {
  struct pbuf *p, *ptr;
  struct ip_addr *fromaddr;
  u16_t fromport;
  err_t err;
};

struct netconn {
  enum netconn_type type;
  enum netconn_state state;
  union {
    struct tcp_pcb *tcp;
    struct udp_pcb *udp;
  } pcb;
  err_t err;
  sys_mbox_t mbox;
  sys_mbox_t recvmbox;
  sys_mbox_t acceptmbox;
  sys_sem_t sem;
/* *****Added by DJH */
  int socket;
  void (* callback)(struct netconn *, enum netconn_evt); =20
/* *****             */
};

/* Network buffer functions: */
struct netbuf *   netbuf_new      (void);
void              netbuf_delete   (struct netbuf *buf);
void *            netbuf_alloc    (struct netbuf *buf, u16_t size);
void              netbuf_free     (struct netbuf *buf);
void              netbuf_ref      (struct netbuf *buf,
                                   void *dataptr, u16_t size);
void              netbuf_chain    (struct netbuf *head,
                                   struct netbuf *tail);

u16_t             netbuf_len      (struct netbuf *buf);
err_t             netbuf_data     (struct netbuf *buf,
                                   void **dataptr, u16_t *len);
s8_t              netbuf_next     (struct netbuf *buf);
void              netbuf_first    (struct netbuf *buf);

void              netbuf_copy     (struct netbuf *buf,
                                   void *dataptr, u16_t len);
struct ip_addr *  netbuf_fromaddr (struct netbuf *buf);
u16_t             netbuf_fromport (struct netbuf *buf);

/* Network connection functions: */
struct netconn *  netconn_new     (enum netconn_type type);
/* *****Added by DJH */
struct
netconn *netconn_new_with_callback(enum netconn_type t,
                                   void (*callback)(struct netconn *, =
enum netconn_evt));
/* *****             */
err_t             netconn_delete  (struct netconn *conn);
enum netconn_type netconn_type    (struct netconn *conn);
err_t             netconn_peer    (struct netconn *conn,
                                   struct ip_addr **addr,
                                   u16_t *port);
err_t             netconn_addr    (struct netconn *conn,
                                   struct ip_addr **addr,
                                   u16_t *port);
err_t             netconn_bind    (struct netconn *conn,
                                   struct ip_addr *addr,
                                   u16_t port);
err_t             netconn_connect (struct netconn *conn,
                                   struct ip_addr *addr,
                                   u16_t port);
err_t             netconn_listen  (struct netconn *conn);
struct netconn *  netconn_accept  (struct netconn *conn);
struct netbuf *   netconn_recv    (struct netconn *conn);
err_t             netconn_send    (struct netconn *conn,
                                   struct netbuf *buf);
err_t             netconn_write   (struct netconn *conn,
                                   void *dataptr, u16_t size,
                                   u8_t copy);
err_t             netconn_close   (struct netconn *conn);

err_t             netconn_err     (struct netconn *conn);

#endif /* __LWIP_API_H__ */



------=_NextPart_000_000D_01C2A52C.35B69F20
Content-Type: application/octet-stream;
        name="cc.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="cc.h"

/*
 * Copyright (c) 2001, Swedish Institute of Computer Science.
 * All rights reserved.=20
 *
 * Redistribution and use in source and binary forms, with or without=20
 * modification, are permitted provided that the following conditions=20
 * are met:=20
 * 1. Redistributions of source code must retain the above copyright=20
 *    notice, this list of conditions and the following disclaimer.=20
 * 2. Redistributions in binary form must reproduce the above copyright=20
 *    notice, this list of conditions and the following disclaimer in =
the=20
 *    documentation and/or other materials provided with the =
distribution.=20
 * 3. Neither the name of the Institute nor the names of its =
contributors=20
 *    may be used to endorse or promote products derived from this =
software=20
 *    without specific prior written permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' =
AND=20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE =

 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
PURPOSE=20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE =
LIABLE=20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
CONSEQUENTIAL=20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
GOODS=20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) =

 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
STRICT=20
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY =
WAY=20
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
OF=20
 * SUCH DAMAGE.=20
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 * $Id: cc.h,v 1.1 2001/12/12 10:00:56 adam Exp $
 */
#ifndef __CC_H__
#define __CC_H__

#include <types.h>

// typedef unsigned   char    u8_t;
// typedef signed     char    s8_t;
// typedef unsigned   short   u16_t;
// typedef signed     short   s16_t;
// typedef unsigned   long    u32_t;
// typedef signed     long    s32_t;

typedef u32_t mem_ptr_t;

#define PACK_STRUCT_BEGIN #pragma pack(1,1,0)
#define PACK_STRUCT_STRUCT
#define ALIGN_STRUCT_8_BEGIN #pragma pack(1,8,0)
#define ALIGN_STRUCT_END #pragma pack()
#define PACK_STRUCT_END #pragma pack()
#define PACK_STRUCT_FIELD(x) x


#define _SYS_TYPES_FD_SET
#define NBBY    8               /* number of bits in a byte */

#ifndef FD_SETSIZE
#define FD_SETSIZE      64
#endif /* FD_SETSIZE */

typedef long    fd_mask;
#define NFDBITS (sizeof (fd_mask) * NBBY)       /* bits per mask */
#ifndef howmany
#define howmany(x,y)    (((x)+((y)-1))/(y))
#endif /* howmany */

typedef struct _types_fd_set {
        fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;

#define fd_set _types_fd_set

#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |=3D (1L << ((n) % =
NFDBITS)))
#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &=3D ~(1L << ((n) % =
NFDBITS)))
#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % =
NFDBITS)))
#define FD_ZERO(p)       do {                   \
     size_t __i;                                \
     char *__tmp =3D (char *)p;                   \
     for (__i =3D 0; __i < sizeof (*(p)); ++__i)  \
       *__tmp++ =3D 0;                            \
} while (0)

#endif /* __CC_H__ */

------=_NextPart_000_000D_01C2A52C.35B69F20--

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




reply via email to

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