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; }
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; }
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; }