Example #1
0
int uip_backlogdestroy(FAR struct uip_conn *conn)
{
  FAR struct uip_backlog_s     *blg;
  FAR struct uip_blcontainer_s *blc;
  FAR struct uip_conn          *blconn;

  nllvdbg("conn=%p\n", conn);

#ifdef CONFIG_DEBUG
  if (!conn)
    {
      return -EINVAL;
    }
#endif

  /* Make sure that the connection has a backlog to be destroyed */

  if (conn->backlog)
    {
       /* Remove the backlog structure reference from the connection */

       blg           = conn->backlog;
       conn->backlog = NULL;

       /* Handle any pending connections in the backlog */

       while ((blc = (FAR struct uip_blcontainer_s*)sq_remfirst(&blg->bl_pending)) != NULL)
         {
           blconn = blc->bc_conn;
           if (blconn)
             {
               /* REVISIT -- such connections really need to be gracefully closed */

               blconn->blparent = NULL;
               blconn->backlog  = NULL;
               blconn->crefs    = 0;
               uip_tcpfree(blconn);
             }
         }

       /* Then free the entire backlog structure */

       kfree(blg);
    }

  return OK;
}
Example #2
0
struct uip_conn *uip_tcpalloc(void)
{
  struct uip_conn *conn;
  uip_lock_t flags;

  /* Because this routine is called from both interrupt level and
   * and from user level, we have not option but to disable interrupts
   * while accessing g_free_tcp_connections[];
   */

  flags = uip_lock();

  /* Return the entry from the head of the free list */

  conn = (struct uip_conn *)dq_remfirst(&g_free_tcp_connections);

  /* Is the free list empty? */

  if (!conn)
    {
      /* As a fallback, check for connection structures which are not
       * established yet.
       *
       * Search the active connection list for the oldest connection
       * that is not in the UIP_ESTABLISHED state.
       */

      struct uip_conn *tmp = g_active_tcp_connections.head;
      while (tmp)
        {
          nllvdbg("conn: %p state: %02x\n", tmp, tmp->tcpstateflags);

          /* Is this connection in some state other than UIP_ESTABLISHED
           * state?
           */

          if (tmp->tcpstateflags != UIP_ESTABLISHED)
            {
              /* Yes.. Is it the oldest one we have seen so far? */

              if (!conn || tmp->timer > conn->timer)
                {
                  /* Yes.. remember it */

                  conn = tmp;
                }
            }

          /* Look at the next active connection */

          tmp = tmp->node.flink;
        }

      /* Did we find a connection that we can re-use? */

      if (conn != NULL)
        {
          nlldbg("Closing unestablished connection: %p\n", conn);

          /* Yes... free it.  This will remove the connection from the list
           * of active connections and release all resources held by the
           * connection.
           *
           * REVISIT:  Could there be any higher level, socket interface
           * that needs to be informed that we did this to them?
           */

          uip_tcpfree(conn);

          /* Now there is guaranteed to be one free connection.  Get it! */

          conn = (struct uip_conn *)dq_remfirst(&g_free_tcp_connections);
        }
    }

  uip_unlock(flags);

  /* Mark the connection allocated */

  if (conn)
    {
      memset(conn, 0, sizeof(struct uip_conn));
      conn->tcpstateflags = UIP_ALLOCATED;
    }

  return conn;
}
Example #3
0
int psock_close(FAR struct socket *psock)
{
  int err;

  /* Verify that the sockfd corresponds to valid, allocated socket */

  if (!psock || psock->s_crefs <= 0)
    {
      err = EBADF;
      goto errout;
    }

  /* We perform the uIP close operation only if this is the last count on the socket.
   * (actually, I think the socket crefs only takes the values 0 and 1 right now).
   */

  if (psock->s_crefs <= 1)
    {
      /* Perform uIP side of the close depending on the protocol type */

      switch (psock->s_type)
        {
#ifdef CONFIG_NET_TCP
          case SOCK_STREAM:
            {
              struct uip_conn *conn = psock->s_conn;

              /* Is this the last reference to the connection structure (there
               * could be more if the socket was dup'ed.
               */

              if (conn->crefs <= 1)
                {
                  /* Yes... free the connection structure */

                  uip_unlisten(conn);          /* No longer accepting connections */
                  netclose_disconnect(psock);  /* Break any current connections */
                  conn->crefs = 0;             /* No more references on the connection */
                  uip_tcpfree(conn);           /* Free uIP resources */
                }
              else
                {
                  /* No.. Just decrement the reference count */

                  conn->crefs--;
                }
            }
            break;
#endif

#ifdef CONFIG_NET_UDP
          case SOCK_DGRAM:
            {
              struct uip_udp_conn *conn = psock->s_conn;

              /* Is this the last reference to the connection structure (there
               * could be more if the socket was dup'ed.
               */

              if (conn->crefs <= 1)
                {
                  /* Yes... free the connection structure */

                  conn->crefs = 0;             /* No more references on the connection */
                  uip_udpfree(psock->s_conn);  /* Free uIP resources */
                }
              else
                {
                  /* No.. Just decrement the reference count */

                  conn->crefs--;
                }
            }
            break;
#endif

          default:
            err = EBADF;
            goto errout;
        }
    }

  /* Then release our reference on the socket structure containing the connection */

  sock_release(psock);
  return OK;

errout:
  errno = err;
  return ERROR;
}