/**************************************************************************** * net/socket/net_sockets.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 #include #include #include #include #include #include #include #include #include "socket/socket.h" /**************************************************************************** * Private Functions ****************************************************************************/ static void _net_semtake(FAR struct socketlist *list) { net_lockedwait_uninterruptible(&list->sl_sem); } #define _net_semgive(list) nxsem_post(&list->sl_sem) /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: net_initlist * * Description: * Initialize a list of sockets for a new task * * Input Parameters: * list -- A reference to the pre-allocated socket list to be initialized. * * Returned Value: * None * ****************************************************************************/ void net_initlist(FAR struct socketlist *list) { /* Initialize the list access mutex */ nxsem_init(&list->sl_sem, 0, 1); } /**************************************************************************** * Name: net_releaselist * * Description: * Release resources held by the socket list * * Input Parameters: * list - A reference to the pre-allocated socket list to be un- * initialized. * * Returned Value: * None * ****************************************************************************/ void net_releaselist(FAR struct socketlist *list) { int ndx; DEBUGASSERT(list); /* Close each open socket in the list. */ for (ndx = 0; ndx < CONFIG_NSOCKET_DESCRIPTORS; ndx++) { FAR struct socket *psock = &list->sl_sockets[ndx]; if (psock->s_crefs > 0) { psock_close(psock); } } /* Destroy the semaphore */ nxsem_destroy(&list->sl_sem); } /**************************************************************************** * Name: sockfd_allocate * * Description: * Allocate a socket descriptor * * Input Parameters: * Lowest socket descriptor index to be used. * * Returned Value: * On success, a socket descriptor >= minsd is returned. A negated errno * value is returned on failure. * ****************************************************************************/ int sockfd_allocate(int minsd) { FAR struct socketlist *list; int i; /* Get the socket list for this task/thread */ list = nxsched_get_sockets(); if (list) { /* Search for a socket structure with no references */ _net_semtake(list); for (i = minsd; i < CONFIG_NSOCKET_DESCRIPTORS; i++) { /* Are there references on this socket? */ if (!list->sl_sockets[i].s_crefs) { /* No take the reference and return the index + an offset * as the socket descriptor. */ memset(&list->sl_sockets[i], 0, sizeof(struct socket)); list->sl_sockets[i].s_crefs = 1; _net_semgive(list); return i + __SOCKFD_OFFSET; } } _net_semgive(list); } return ERROR; } /**************************************************************************** * Name: psock_release * * Description: * Free a socket. * * Input Parameters: * psock - A reference to the socket instance to be freed. * * Returned Value: * None * ****************************************************************************/ void psock_release(FAR struct socket *psock) { if (psock != NULL) { /* Decrement the count if there the socket will persist * after this. */ if (psock->s_crefs > 1) { psock->s_crefs--; } else { /* The socket will not persist... reset it */ memset(psock, 0, sizeof(struct socket)); } } } /**************************************************************************** * Name: sockfd_release * * Description: * Free the socket by its socket descriptor. * * Input Parameters: * sockfd - Socket descriptor identifies the socket to be released. * * Returned Value: * None * ****************************************************************************/ void sockfd_release(int sockfd) { /* Get the socket structure for this sockfd */ FAR struct socket *psock = sockfd_socket(sockfd); if (psock) { /* Take the list semaphore so that there will be no accesses * to this socket structure. */ FAR struct socketlist *list = nxsched_get_sockets(); if (list) { _net_semtake(list); psock_release(psock); _net_semgive(list); } } } /**************************************************************************** * Name: sockfd_socket * * Description: * Given a socket descriptor, return the underlying socket structure. * * Input Parameters: * sockfd - The socket descriptor index to use. * * Returned Value: * On success, a reference to the socket structure associated with the * the socket descriptor is returned. NULL is returned on any failure. * ****************************************************************************/ FAR struct socket *sockfd_socket(int sockfd) { FAR struct socketlist *list; int ndx = sockfd - __SOCKFD_OFFSET; if (ndx >= 0 && ndx < CONFIG_NSOCKET_DESCRIPTORS) { list = nxsched_get_sockets(); if (list) { return &list->sl_sockets[ndx]; } } return NULL; }