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; }
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_PKT case SOCK_RAW: { FAR struct pkt_conn_s *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 */ pkt_free(psock->s_conn); /* Free uIP resources */ } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif #ifdef CONFIG_NET_TCP case SOCK_STREAM: { FAR struct tcp_conn_s *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... then perform the disconnection now */ tcp_unlisten(conn); /* No longer accepting connections */ conn->crefs = 0; /* Discard our reference to the connection */ err = netclose_disconnect(psock); /* Break any current connections */ if (err < 0) { /* This would normally occur only if there is a timeout * from a lingering close. */ goto errout_with_psock; } } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { FAR struct udp_conn_s *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 */ udp_free(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; #ifdef CONFIG_NET_TCP errout_with_psock: sock_release(psock); #endif errout: set_errno(err); return ERROR; }
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). * * It is possible for a psock to have no connection, e.g. a TCP socket * waiting in accept. */ if (psock->s_crefs <= 1 && psock->s_conn != NULL) { /* Perform uIP side of the close depending on the protocol type */ switch (psock->s_type) { #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) case SOCK_STREAM: { #ifdef CONFIG_NET_LOCAL_STREAM #ifdef CONFIG_NET_TCP if (psock->s_domain == PF_LOCAL) #endif { /* Release our reference to the local connection structure */ local_close(psock); } #endif /* CONFIG_NET_LOCAL_STREAM */ #ifdef CONFIG_NET_TCP #ifdef CONFIG_NET_LOCAL_STREAM else #endif { FAR struct tcp_conn_s *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... then perform the disconnection now */ tcp_unlisten(conn); /* No longer accepting connections */ conn->crefs = 0; /* Discard our reference to the connection */ /* Break any current connections */ err = netclose_disconnect(psock); if (err < 0) { /* This would normally occur only if there is a * timeout from a lingering close. */ goto errout_with_psock; } /* Stop the network monitor */ net_stopmonitor(conn); } else { /* No.. Just decrement the reference count */ conn->crefs--; } } #endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL_STREAM */ } break; #endif #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) case SOCK_DGRAM: { #ifdef CONFIG_NET_LOCAL_DGRAM #ifdef CONFIG_NET_UDP if (psock->s_domain == PF_LOCAL) #endif { /* Release our reference to the local connection structure */ local_close(psock); } #endif /* CONFIG_NET_LOCAL_DGRAM */ #ifdef CONFIG_NET_UDP #ifdef CONFIG_NET_LOCAL_DGRAM else #endif { FAR struct udp_conn_s *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; udp_free(psock->s_conn); } else { /* No.. Just decrement the reference count */ conn->crefs--; } } #endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */ } break; #endif #ifdef CONFIG_NET_PKT case SOCK_RAW: { FAR struct pkt_conn_s *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 */ pkt_free(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; #ifdef CONFIG_NET_TCP errout_with_psock: sock_release(psock); #endif errout: set_errno(err); return ERROR; }