mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 09:49:21 +08:00
1fe07d0838
Our net socket connection allocations are powerful but redundant because they're implemented once in each protocol. This is not good for further optimizing and extending to other allocations, so maybe we can add a common implementation for the usage. Impact: 1. We add a `struct net_bufpool_s` as pool descriptor, which may use a little bit more memory than previous implementation (~28Bytes). 2. We share same functions between pools, so code size may shrink under some scenarios. Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
310 lines
9 KiB
C
310 lines
9 KiB
C
/****************************************************************************
|
|
* net/usrsock/usrsock_conn.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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 <nuttx/config.h>
|
|
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
#include <arch/irq.h>
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
#include <nuttx/mutex.h>
|
|
#include <nuttx/semaphore.h>
|
|
#include <nuttx/net/netconfig.h>
|
|
#include <nuttx/net/net.h>
|
|
#include <nuttx/net/usrsock.h>
|
|
|
|
#include "usrsock/usrsock.h"
|
|
#include "utils/utils.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#ifndef CONFIG_NET_USRSOCK_MAX_CONNS
|
|
# define CONFIG_NET_USRSOCK_MAX_CONNS 0
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/* The array containing all usrsock connections. */
|
|
|
|
NET_BUFPOOL_DECLARE(g_usrsock_connections, sizeof(struct usrsock_conn_s),
|
|
CONFIG_NET_USRSOCK_PREALLOC_CONNS,
|
|
CONFIG_NET_USRSOCK_ALLOC_CONNS,
|
|
CONFIG_NET_USRSOCK_MAX_CONNS);
|
|
static mutex_t g_free_lock = NXMUTEX_INITIALIZER;
|
|
|
|
/* A list of all allocated usrsock connections */
|
|
|
|
static dq_queue_t g_active_usrsock_connections;
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_alloc()
|
|
*
|
|
* Description:
|
|
* Allocate a new, uninitialized usrsock connection structure. This is
|
|
* normally something done by the implementation of the socket() API
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct usrsock_conn_s *usrsock_alloc(void)
|
|
{
|
|
FAR struct usrsock_conn_s *conn;
|
|
|
|
/* The free list is protected by a a mutex. */
|
|
|
|
nxmutex_lock(&g_free_lock);
|
|
|
|
conn = NET_BUFPOOL_TRYALLOC(g_usrsock_connections);
|
|
if (conn)
|
|
{
|
|
/* Make sure that the connection is marked as uninitialized */
|
|
|
|
nxsem_init(&conn->resp.sem, 0, 1);
|
|
conn->usockid = USRSOCK_USOCKID_INVALID;
|
|
conn->state = USRSOCK_CONN_STATE_UNINITIALIZED;
|
|
|
|
/* Enqueue the connection into the active list */
|
|
|
|
dq_addlast(&conn->sconn.node, &g_active_usrsock_connections);
|
|
}
|
|
|
|
nxmutex_unlock(&g_free_lock);
|
|
return conn;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_free()
|
|
*
|
|
* Description:
|
|
* Free a usrsock connection structure that is no longer in use. This
|
|
* should be done by the implementation of close().
|
|
*
|
|
****************************************************************************/
|
|
|
|
void usrsock_free(FAR struct usrsock_conn_s *conn)
|
|
{
|
|
/* The free list is protected by a mutex. */
|
|
|
|
DEBUGASSERT(conn->crefs == 0);
|
|
|
|
nxmutex_lock(&g_free_lock);
|
|
|
|
/* Remove the connection from the active list */
|
|
|
|
dq_rem(&conn->sconn.node, &g_active_usrsock_connections);
|
|
|
|
/* Reset structure */
|
|
|
|
nxsem_destroy(&conn->resp.sem);
|
|
|
|
/* Free the connection. */
|
|
|
|
NET_BUFPOOL_FREE(g_usrsock_connections, conn);
|
|
|
|
nxmutex_unlock(&g_free_lock);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_nextconn()
|
|
*
|
|
* Description:
|
|
* Traverse the list of allocated usrsock connections
|
|
*
|
|
* Assumptions:
|
|
* This function is called from usrsock device logic.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct usrsock_conn_s *usrsock_nextconn(FAR struct usrsock_conn_s *conn)
|
|
{
|
|
if (!conn)
|
|
{
|
|
return (FAR struct usrsock_conn_s *)g_active_usrsock_connections.head;
|
|
}
|
|
else
|
|
{
|
|
return (FAR struct usrsock_conn_s *)conn->sconn.node.flink;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_active()
|
|
*
|
|
* Description:
|
|
* Find a connection structure that is the appropriate
|
|
* connection for usrsock
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct usrsock_conn_s *usrsock_active(int16_t usockid)
|
|
{
|
|
FAR struct usrsock_conn_s *conn = NULL;
|
|
|
|
while ((conn = usrsock_nextconn(conn)) != NULL)
|
|
{
|
|
if (conn->usockid == usockid)
|
|
{
|
|
return conn;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_setup_request_callback()
|
|
****************************************************************************/
|
|
|
|
int usrsock_setup_request_callback(FAR struct usrsock_conn_s *conn,
|
|
FAR struct usrsock_reqstate_s *pstate,
|
|
FAR devif_callback_event_t event,
|
|
uint16_t flags)
|
|
{
|
|
int ret = -EBUSY;
|
|
|
|
nxsem_init(&pstate->recvsem, 0, 0);
|
|
|
|
pstate->conn = conn;
|
|
pstate->result = -EAGAIN;
|
|
pstate->completed = false;
|
|
pstate->unlock = false;
|
|
|
|
/* Set up the callback in the connection */
|
|
|
|
pstate->cb = devif_callback_alloc(NULL, &conn->sconn.list,
|
|
&conn->sconn.list_tail);
|
|
if (pstate->cb)
|
|
{
|
|
/* Take a lock since only one outstanding request is allowed */
|
|
|
|
if ((flags & USRSOCK_EVENT_REQ_COMPLETE) != 0)
|
|
{
|
|
net_sem_wait_uninterruptible(&conn->resp.sem);
|
|
pstate->unlock = true;
|
|
}
|
|
|
|
/* Set up the connection event handler */
|
|
|
|
pstate->cb->flags = flags;
|
|
pstate->cb->priv = (FAR void *)pstate;
|
|
pstate->cb->event = event;
|
|
|
|
ret = OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_setup_data_request_callback()
|
|
****************************************************************************/
|
|
|
|
int usrsock_setup_data_request_callback(
|
|
FAR struct usrsock_conn_s *conn,
|
|
FAR struct usrsock_data_reqstate_s *pstate,
|
|
FAR devif_callback_event_t event,
|
|
uint16_t flags)
|
|
{
|
|
pstate->valuelen = 0;
|
|
pstate->valuelen_nontrunc = 0;
|
|
return usrsock_setup_request_callback(conn, &pstate->reqstate, event,
|
|
flags);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_teardown_request_callback()
|
|
****************************************************************************/
|
|
|
|
void usrsock_teardown_request_callback(FAR struct usrsock_reqstate_s *pstate)
|
|
{
|
|
FAR struct usrsock_conn_s *conn = pstate->conn;
|
|
|
|
if (pstate->unlock)
|
|
{
|
|
nxsem_post(&conn->resp.sem);
|
|
}
|
|
|
|
/* Make sure that no further events are processed */
|
|
|
|
devif_conn_callback_free(NULL, pstate->cb, &conn->sconn.list,
|
|
&conn->sconn.list_tail);
|
|
nxsem_destroy(&pstate->recvsem);
|
|
|
|
pstate->cb = NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_setup_datain
|
|
****************************************************************************/
|
|
|
|
void usrsock_setup_datain(FAR struct usrsock_conn_s *conn,
|
|
FAR struct iovec *iov, unsigned int iovcnt)
|
|
{
|
|
unsigned int i;
|
|
|
|
conn->resp.datain.iov = iov;
|
|
conn->resp.datain.pos = 0;
|
|
conn->resp.datain.total = 0;
|
|
conn->resp.datain.iovcnt = iovcnt;
|
|
|
|
for (i = 0; i < iovcnt; i++)
|
|
{
|
|
conn->resp.datain.total += iov[i].iov_len;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: usrsock_initialize()
|
|
*
|
|
* Description:
|
|
* Initialize the User Socket connection structures. Called once and only
|
|
* from the networking layer.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void usrsock_initialize(void)
|
|
{
|
|
NET_BUFPOOL_INIT(g_usrsock_connections);
|
|
|
|
/* Register /dev/usrsock character device. */
|
|
|
|
usrsock_register();
|
|
}
|
|
|
|
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
|