/**************************************************************************** * net/local/local_release.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL) #include #include #include #include #include #include #include "local/local.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: local_release * * Description: * If the local, Unix domain socket is in the connected state, then * disconnect it. Release the local connection structure in any event * * Input Parameters: * conn - A reference to local connection structure * ****************************************************************************/ int local_release(FAR struct local_conn_s *conn) { /* There should be no references on this structure */ DEBUGASSERT(conn->lc_crefs == 0); net_lock(); #ifdef CONFIG_NET_LOCAL_STREAM /* We should not bet here with state LOCAL_STATE_ACCEPT. That is an * internal state that should be atomic with respect to socket operations. */ DEBUGASSERT(conn->lc_state != LOCAL_STATE_ACCEPT); if (conn->lc_state == LOCAL_STATE_CONNECTING) { FAR struct local_conn_s *server = NULL; FAR struct local_conn_s *client; FAR dq_entry_t *waiter = NULL; while ((server = local_nextconn(server)) && waiter == NULL) { if (server->lc_state == LOCAL_STATE_LISTENING) { for (waiter = dq_peek(&server->u.server.lc_waiters); waiter; waiter = dq_next(&client->u.client.lc_waiter)) { if (&conn->u.client.lc_waiter == waiter) { dq_rem(waiter, &server->u.server.lc_waiters); server->u.server.lc_pending--; break; } client = container_of(waiter, struct local_conn_s, u.client.lc_waiter); } } } } /* Is the socket is listening socket (SOCK_STREAM server) */ else if (conn->lc_state == LOCAL_STATE_LISTENING) { FAR struct local_conn_s *client; FAR dq_entry_t *waiter; DEBUGASSERT(conn->lc_proto == SOCK_STREAM); /* Are there still clients waiting for a connection to the server? */ for (waiter = dq_peek(&conn->u.server.lc_waiters); waiter; waiter = dq_next(&client->u.client.lc_waiter)) { client = container_of(waiter, struct local_conn_s, u.client.lc_waiter); client->u.client.lc_result = -ENOTCONN; nxsem_post(&client->lc_waitsem); local_event_pollnotify(client, POLLOUT); } conn->u.server.lc_pending = 0; } #endif /* CONFIG_NET_LOCAL_STREAM */ /* For the remaining states (LOCAL_STATE_UNBOUND and LOCAL_STATE_UNBOUND), * we simply free the connection structure. */ /* Free the connection structure */ local_free(conn); net_unlock(); return OK; } #endif /* CONFIG_NET && CONFIG_NET_LOCAL */